[algogeeks] Re: search a 2d sorted array in less than O(n)

2010-09-27 Thread prodigy

Actual complexity of above algorithm = O(n^1.6)

On Sep 27, 8:19 am, Gene gene.ress...@gmail.com wrote:
 If the array is m by n, pick the element a[m/2][n/2], i.e. the one in
 the middle.  There are now 3 possibilities:

 1) The middle element is the one you're looking for, so you're done.
 2) The element you're looking for is smaller.  In this case you can
 throw out about 1/4 of the array: everything right and downward from
 a[m/2][n/2] (including row m/2 and column n/2) because these elements
 are all larger than the middle one.
 3) The element you're looking for is larger.  In this case you can
 again throw out about 1/4 of the array: everything left and upward
 from a[m/2][n/2] inclusive.

 Then you can search the remaining 3/4 of the array recursively.

 By throwing away 1/4 of mn elements at each step, you can easily work
 out the recurrence to see you'll get O(log mn) = O(log(max(m, n)))
 performance.

 Here is code and a very quick unit test:

 #include stdio.h
 #include stdlib.h

 typedef int SORTED_ARRAY[100][100];

 /* Look for x in row- and column-sorted a[i0..i1][j0..j1].
    Put indices in *i and *j and return 1 if found,
    else return 0.
  */
 int search(SORTED_ARRAY a, int x,
            int i0, int i1,
            int j0, int j1,
            int *i, int *j)
 {
   if (i0 = i1  j0 = j1) {
     int mi = (i0 + i1) / 2;
     int mj = (j0 + j1) / 2;
     if (x == a[mi][mj]) {
       *i = mi; *j = mj;
       return 1;
     }
     return (x  a[mi][mj]) ?
       search(a, x, i0, mi - 1, j0, mj - 1, i, j) ||
       search(a, x, i0, mi - 1, mj, j1, i, j) ||
       search(a, x, mi, i1, j0, mj - 1, i, j)
     :
       search(a, x, mi + 1, i1, mj + 1, j1, i, j) ||
       search(a, x, i0, mi, mj + 1, j1, i, j) ||
       search(a, x, mi + 1, i1, j0, mj, i, j);
   }
   return 0;

 }

 int max(int x, int y) { return x  y ? x : y; }

 int main(void)
 {
   int i, j, m, n, ri, rj;
   SORTED_ARRAY a;

   // A small unit test. Build a m x n
   // sorted array with random differences.
   m = 100; n = 100;
   a[0][0] = 0;
   for (i = 1; i  m; i++)
     a[i][0] = a[i - 1][0] + rand() % 1000;
   for (j = 1; j  n; j++) {
     a[0][j] = a[0][j - 1] + rand() % 1000;
     for (i = 1; i  m; i++)
       a[i][j] = max(a[i - 1][j], a[i][j - 1]) + rand() % 1000;
   }
   for (i = 0; i  m; i++) {
     for (j = 0; j  n; j++) {
       printf(%8d, a[i][j]);
     }
     printf(\n);
   }
   for (i = 0; i  m; i++) {
     for (j = 32; j  n; j++) {
       int r = search(a, a[i][j], 0, m - 1, 0, n - 1, ri, rj);
       if (!r) {
         printf(failed at a[%d][%d]\n, i, j, a[i][j]);
         return 1;
       }
       else if (a[ri][rj] != a[i][j]) {
         printf(mistake at a[%d][%d]=%d: found a[%d][%d]=%d\n,
                i, j, a[i][j], ri, rj, a[ri][rj]);
         return 1;
       }
     }
   }
   printf(pass!\n);

   return 0;

 }

 On Sep 21, 7:40 am, jagadish jagadish1...@gmail.com wrote:

  Hi all,
  Given a 2d array which is sorted row wise and column wise as well,
  find a specific element in it in LESS THAN O(n).
  PS: an O(n) solution would involve skipping a column or a row each
  time from the search and moving accordingly.
  Solution less than O(n) is desirable!

-- 
You received this message because you are subscribed to the Google Groups 
Algorithm Geeks group.
To post to this group, send email to algoge...@googlegroups.com.
To unsubscribe from this group, send email to 
algogeeks+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/algogeeks?hl=en.



[algogeeks] Re: search a 2d sorted array in less than O(n)

2010-09-27 Thread sourav
I feel the binary search approach as given by Saurabh Singh or like
moving from top right row, doing binary search in the row 0, find the
element being searched (say x) or one less than that (say y), followed
by binary search in the column below 'y' and proceeding in this way
can give a less than O(n) solution.

Please provide your comments in any

Thanks
Sourav

On Sep 27, 11:09 am, prodigy 1abhishekshu...@gmail.com wrote:
 Actual complexity of above algorithm = O(n^1.6)

 On Sep 27, 8:19 am, Gene gene.ress...@gmail.com wrote:

  If the array is m by n, pick the element a[m/2][n/2], i.e. the one in
  the middle.  There are now 3 possibilities:

  1) The middle element is the one you're looking for, so you're done.
  2) The element you're looking for is smaller.  In this case you can
  throw out about 1/4 of the array: everything right and downward from
  a[m/2][n/2] (including row m/2 and column n/2) because these elements
  are all larger than the middle one.
  3) The element you're looking for is larger.  In this case you can
  again throw out about 1/4 of the array: everything left and upward
  from a[m/2][n/2] inclusive.

  Then you can search the remaining 3/4 of the array recursively.

  By throwing away 1/4 of mn elements at each step, you can easily work
  out the recurrence to see you'll get O(log mn) = O(log(max(m, n)))
  performance.

  Here is code and a very quick unit test:

  #include stdio.h
  #include stdlib.h

  typedef int SORTED_ARRAY[100][100];

  /* Look for x in row- and column-sorted a[i0..i1][j0..j1].
     Put indices in *i and *j and return 1 if found,
     else return 0.
   */
  int search(SORTED_ARRAY a, int x,
             int i0, int i1,
             int j0, int j1,
             int *i, int *j)
  {
    if (i0 = i1  j0 = j1) {
      int mi = (i0 + i1) / 2;
      int mj = (j0 + j1) / 2;
      if (x == a[mi][mj]) {
        *i = mi; *j = mj;
        return 1;
      }
      return (x  a[mi][mj]) ?
        search(a, x, i0, mi - 1, j0, mj - 1, i, j) ||
        search(a, x, i0, mi - 1, mj, j1, i, j) ||
        search(a, x, mi, i1, j0, mj - 1, i, j)
      :
        search(a, x, mi + 1, i1, mj + 1, j1, i, j) ||
        search(a, x, i0, mi, mj + 1, j1, i, j) ||
        search(a, x, mi + 1, i1, j0, mj, i, j);
    }
    return 0;

  }

  int max(int x, int y) { return x  y ? x : y; }

  int main(void)
  {
    int i, j, m, n, ri, rj;
    SORTED_ARRAY a;

    // A small unit test. Build a m x n
    // sorted array with random differences.
    m = 100; n = 100;
    a[0][0] = 0;
    for (i = 1; i  m; i++)
      a[i][0] = a[i - 1][0] + rand() % 1000;
    for (j = 1; j  n; j++) {
      a[0][j] = a[0][j - 1] + rand() % 1000;
      for (i = 1; i  m; i++)
        a[i][j] = max(a[i - 1][j], a[i][j - 1]) + rand() % 1000;
    }
    for (i = 0; i  m; i++) {
      for (j = 0; j  n; j++) {
        printf(%8d, a[i][j]);
      }
      printf(\n);
    }
    for (i = 0; i  m; i++) {
      for (j = 32; j  n; j++) {
        int r = search(a, a[i][j], 0, m - 1, 0, n - 1, ri, rj);
        if (!r) {
          printf(failed at a[%d][%d]\n, i, j, a[i][j]);
          return 1;
        }
        else if (a[ri][rj] != a[i][j]) {
          printf(mistake at a[%d][%d]=%d: found a[%d][%d]=%d\n,
                 i, j, a[i][j], ri, rj, a[ri][rj]);
          return 1;
        }
      }
    }
    printf(pass!\n);

    return 0;

  }

  On Sep 21, 7:40 am, jagadish jagadish1...@gmail.com wrote:

   Hi all,
   Given a 2d array which is sorted row wise and column wise as well,
   find a specific element in it in LESS THAN O(n).
   PS: an O(n) solution would involve skipping a column or a row each
   time from the search and moving accordingly.
   Solution less than O(n) is desirable!

-- 
You received this message because you are subscribed to the Google Groups 
Algorithm Geeks group.
To post to this group, send email to algoge...@googlegroups.com.
To unsubscribe from this group, send email to 
algogeeks+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/algogeeks?hl=en.



[algogeeks] Re: search a 2d sorted array in less than O(n)

2010-09-27 Thread Gene
Well, friend, we're both wrong.

The algorithm will find 6 just fine. It will choose 3 as the middle
element. Since 6 is bigger, it will throw away the subarray

1 2
2 3

and check the other 3 subarrays.  When it checks

6 7
7 8

It will find the 6 on the first try.  I just verified this by running
the code.

Second, I should have solved the recurrence.  You're right that it's ~
n^1.6  .  Throwing away a quarter of the _elements_ isn't good enough
because that number is n^2.

The algorithm is only sublinear in the number of elements, which of
course is worse than the standard algorithm that starts at the lower
left corner and steps along a jagged path of max length ~2n.

But I should have seen that you can split the L-shaped remaining piece
of each subarray into only TWO pieces rather than 3.  So the recursive
calls should have been:

return (x  a[mi][mj]) ?
  search(a, x, i0, mi - 1, j0, j1, i, j) ||
  search(a, x, mi, i1, j0, mj - 1, i, j)
:
  search(a, x, i0, mi, mj + 1, j1, i, j) ||
  search(a, x, mi + 1, i1, j0, j1, i, j);

With this change the recurrence is more complicated, but it should be
faster than n^1.6 .  I'm not going to try it tonight...

On Sep 27, 8:19 am, Nikhil Jindal fundoon...@yahoo.co.in wrote:
 @saurabh.nsit:

 Consider the following array:

 1 2 6 7
 2 3 7 8
 4 5 8 9
 5 7 9 10

 And the item to be searched is 6. As I understand it, using your approach
 you will search 6 in only the second and third row, which will not give the
 correct solution.
 Hope this clears a few doubts.

 @Gene:
 Analysing the complexity of ur algo:

 T(n) = 3*T(n/2) + O(1)

 which is n^(log_2(3)) = n^1.6.

 Cheers
 Nikhil Jindal

 On Sun, Sep 26, 2010 at 11:14 PM, saurabh singh saurabh.n...@gmail.comwrote:





  As you mentioned ultimately element to be searched should either be in row
  'i' (ahead of [i,i] element) or in row i+1 (before [i+1,i+1] element). Since
  each row contain numbers in sorted order so u can do binary search on these
  two rows and ultimately the complexity will be O(logn) only

   On Sun, Sep 26, 2010 at 7:34 PM, Nikhil Jindal 
  fundoon...@yahoo.co.inwrote:

   On Tue, Sep 21, 2010 at 6:05 PM, saurabh singh 
  saurabh.n...@gmail.comwrote:

  solution 1:
  use concept of quad-tree and do binary search in that tree

  solution 2:
  do binary search on major diagonal. ultimately u will narrow down to
  search for element in  2 rows. in these two rows again do binary search.

  How do you narrow down to two rows? Please explain.
  By searching on the diagonal, you get two elements such that one is lesser
  than the number being searched for and the next is greater. let them be 
  i,i,
  and i+1,i+1.

  So you remove the array from 0,0 to i,i and from i+1,i+1 to n-1,n-1. But
  the number could be anywhere in the rest of the array

  any solution will lead you to O(log(n)) time

  On Tue, Sep 21, 2010 at 5:10 PM, jagadish jagadish1...@gmail.comwrote:

  Hi all,
  Given a 2d array which is sorted row wise and column wise as well,
  find a specific element in it in LESS THAN O(n).
  PS: an O(n) solution would involve skipping a column or a row each
  time from the search and moving accordingly.
  Solution less than O(n) is desirable!

  --
  You received this message because you are subscribed to the Google
  Groups Algorithm Geeks group.
  To post to this group, send email to algoge...@googlegroups.com.
  To unsubscribe from this group, send email to
  algogeeks+unsubscr...@googlegroups.comalgogeeks%2bunsubscr...@googlegroups
   .com
  .
  For more options, visit this group at
 http://groups.google.com/group/algogeeks?hl=en.

  --
  Thanks  Regards,
  Saurabh

  --
  You received this message because you are subscribed to the Google Groups
  Algorithm Geeks group.
  To post to this group, send email to algoge...@googlegroups.com.
  To unsubscribe from this group, send email to
  algogeeks+unsubscr...@googlegroups.comalgogeeks%2bunsubscr...@googlegroups
   .com
  .
  For more options, visit this group at
 http://groups.google.com/group/algogeeks?hl=en.

  Please access the attached hyperlink for an important electronic 
  communications 
  disclaimer:http://dce.edu/web/Sections/Standalone/Email_Disclaimer.php

  --

  You received this message because you are subscribed to the Google Groups 
  Algorithm Geeks group.

  To post to this group, send email to algoge...@googlegroups.com.

  To unsubscribe from this group, send email to 
  algogeeks+unsubscr...@googlegroups.com 
  algogeeks%2bunsubscr...@googlegroups.com.

  For more options, visit this group 
  athttp://groups.google.com/group/algogeeks?hl=en.

  --
  Thanks  Regards,
  Saurabh

  --
  You received this message because you are subscribed to the Google Groups
  Algorithm Geeks group.
  To post to this group, send email to algoge...@googlegroups.com.
  To unsubscribe from this group, send email to
  algogeeks+unsubscr...@googlegroups.comalgogeeks%2bunsubscr...@googlegroups 
  .com
  .
  For more options, 

[algogeeks] Re: search a 2d sorted array in less than O(n)

2010-09-26 Thread Gene
If the array is m by n, pick the element a[m/2][n/2], i.e. the one in
the middle.  There are now 3 possibilities:

1) The middle element is the one you're looking for, so you're done.
2) The element you're looking for is smaller.  In this case you can
throw out about 1/4 of the array: everything right and downward from
a[m/2][n/2] (including row m/2 and column n/2) because these elements
are all larger than the middle one.
3) The element you're looking for is larger.  In this case you can
again throw out about 1/4 of the array: everything left and upward
from a[m/2][n/2] inclusive.

Then you can search the remaining 3/4 of the array recursively.

By throwing away 1/4 of mn elements at each step, you can easily work
out the recurrence to see you'll get O(log mn) = O(log(max(m, n)))
performance.

Here is code and a very quick unit test:

#include stdio.h
#include stdlib.h

typedef int SORTED_ARRAY[100][100];

/* Look for x in row- and column-sorted a[i0..i1][j0..j1].
   Put indices in *i and *j and return 1 if found,
   else return 0.
 */
int search(SORTED_ARRAY a, int x,
   int i0, int i1,
   int j0, int j1,
   int *i, int *j)
{
  if (i0 = i1  j0 = j1) {
int mi = (i0 + i1) / 2;
int mj = (j0 + j1) / 2;
if (x == a[mi][mj]) {
  *i = mi; *j = mj;
  return 1;
}
return (x  a[mi][mj]) ?
  search(a, x, i0, mi - 1, j0, mj - 1, i, j) ||
  search(a, x, i0, mi - 1, mj, j1, i, j) ||
  search(a, x, mi, i1, j0, mj - 1, i, j)
:
  search(a, x, mi + 1, i1, mj + 1, j1, i, j) ||
  search(a, x, i0, mi, mj + 1, j1, i, j) ||
  search(a, x, mi + 1, i1, j0, mj, i, j);
  }
  return 0;
}

int max(int x, int y) { return x  y ? x : y; }

int main(void)
{
  int i, j, m, n, ri, rj;
  SORTED_ARRAY a;

  // A small unit test. Build a m x n
  // sorted array with random differences.
  m = 100; n = 100;
  a[0][0] = 0;
  for (i = 1; i  m; i++)
a[i][0] = a[i - 1][0] + rand() % 1000;
  for (j = 1; j  n; j++) {
a[0][j] = a[0][j - 1] + rand() % 1000;
for (i = 1; i  m; i++)
  a[i][j] = max(a[i - 1][j], a[i][j - 1]) + rand() % 1000;
  }
  for (i = 0; i  m; i++) {
for (j = 0; j  n; j++) {
  printf(%8d, a[i][j]);
}
printf(\n);
  }
  for (i = 0; i  m; i++) {
for (j = 32; j  n; j++) {
  int r = search(a, a[i][j], 0, m - 1, 0, n - 1, ri, rj);
  if (!r) {
printf(failed at a[%d][%d]\n, i, j, a[i][j]);
return 1;
  }
  else if (a[ri][rj] != a[i][j]) {
printf(mistake at a[%d][%d]=%d: found a[%d][%d]=%d\n,
   i, j, a[i][j], ri, rj, a[ri][rj]);
return 1;
  }
}
  }
  printf(pass!\n);

  return 0;
}

On Sep 21, 7:40 am, jagadish jagadish1...@gmail.com wrote:
 Hi all,
 Given a 2d array which is sorted row wise and column wise as well,
 find a specific element in it in LESS THAN O(n).
 PS: an O(n) solution would involve skipping a column or a row each
 time from the search and moving accordingly.
 Solution less than O(n) is desirable!

-- 
You received this message because you are subscribed to the Google Groups 
Algorithm Geeks group.
To post to this group, send email to algoge...@googlegroups.com.
To unsubscribe from this group, send email to 
algogeeks+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/algogeeks?hl=en.