0 1 2 3 4 5 6 7 8 9 +-----------------------------+ 0 | 4 6 9 10 12 15 19 22 24 25| 1 | 5 10 11 12 13 18 21 24 26 27| 2 | 6 14 18 21 23 24 26 29 30 33| 3 |10 15 19 24 25 27 31 34 36 37| 4 |11 17 23 25 29 31 33 38 42 43| 5 |15 18 27 29 30 32 35 42 46 50| 6 |16 19 30 34 35 37 41 43 50 51| 7 |20 23 32 37 41 43 44 47 52 53| 8 |24 25 33 40 45 46 49 50 54 57| 9 |26 29 34 41 48 51 55 58 60 62| 10 |30 33 38 43 52 56 58 61 64 67| +-----------------------------+ |
A characteristic of efficient search algorithms is that each probe results in a significant decrease in the size of the search space. As you will recall, in the binary search algorithm, each time an array element is probed (i.e., accessed and compared to the search key), the search space is cut in half. That algorithm exploits the fact that the array elements are in ascending order. (Indeed, binary search is not applicable unless the array elements are in ascending (or, alternatively, descending) order.)
Can the binary search algorithm be generalized to find occurrences of values in a two-dimensional array (i.e., matrix)? The answer is yes, assuming, of course, that its elements are properly ordered. For the purposes of this assignment, that will mean that the elements are strictly increasing along each row and along each column. An example of a 10×11 matrix —call it M— satisfying this condition is shown to the right.
Observe that, in any rectangular region of such a matrix, the largest value is found in its high corner (i.e., bottom right) and its smallest value is found in its low corner (i.e., upper left).
0 1 2 3 4 5 6 7 8 9 +-----------------------------+ 0 | |15 19 22 24 25| 1 | |18 21 24 26 27| 2 | ELIMINATED |24 26 29 30 33| 3 | |27 31 34 36 37| 4 | |31 33 38 42 43| 5 | 30|32 35 42 46 50| +--------------+ | 6 |16 19 30 34 35 37 41 43 50 51| 7 |20 23 32 37 41 43 44 47 52 53| 8 |24 25 33 40 45 46 49 50 54 57| 9 |26 29 34 41 48 51 55 58 60 62| 10 |30 33 38 43 52 56 58 61 64 67| +-----------------------------+ |
The low corner of M is at location (0,0) and its high corner is at location (10,9). We can compute the middle location to be ((0+10)/2, (0+9)/2), or (5,4). There we find 30, which is less than our search key, 38. It follows that 38 cannot possibly occur in the region whose high corner is (5,4), because all values in that region must be 30 or less. Which means that, as the result of this single probe, we can eliminate one-fourth of the search space from further consideration, as illustrated to the right.
The remaining search space (all of which must be searched if we are to be sure to find all locations in which 38 occurs) can be interpreted in three different ways:
Of course, to search in any of the remaining rectangular regions, we can employ the same approach that got us this far. In other words, we search each of the remaining rectangular regions recursively! (The base case would be an empty region.)
0 1 2 3 4 5 6 7 8 9 +-----------------------------+ 0 | 4 6 9 10 12 15 19 22 24 25| 1 | 5 10 11 12 13 18 21 24 26 27| 2 | 6 14 18 21 23 24 26 29 30 33| 3 |10 15 19 24 25 27 31 34 36 37| 4 |11 17 23 25 29 31 33 38 42 43| | +-----------------| 5 |15 18 27 29|30 | 6 |16 19 30 34| | 7 |20 23 32 37| ELIMINATED | 8 |24 25 33 40| | 9 |26 29 34 41| | 10 |30 33 38 43| | +-----------+-----------------+ |
As before, we can interpret the remaining search space to be either a collection of three rectangular regions or, in two different ways, a pair of rectangular regions. In any case, we would then be left to recursively search the relevant regions.
The figures below attempt to generalize the examples described above and to address the possibility that the element probed happens to be the search key. The assumption is that a search for x is to be carried out within a rectangular region whose low corner has coordinates (LR,LC) and whose high corner has coordinates (HR,HC). The coordinates of the middle location are (MR,MC), where MR = (LR + HR)/2 and MC = (LC + HC)/2.
LC MC HC +--------------+-------------+ LR| | |LR | | | | | | | ELIMINATED | | | | | | | | MR| <x| |MR +--------------+ | | | | | | | | | HR| |HR +--------------+-------------+ LC MC HC |
LC MC HC +----------------------------+ LR| |LR | | | | | | | | | +--------------+ MR| |>x |MR | | | | | | | | ELIMINATED | | | | | | | HR| | |HR +-------------+--------------+ LC MC HC |
LC MC HC +---------------+------------+ LR| | |LR | | | | ELIMINATED | | | | | | | | | +-+------------+ MR| |x| |MR +-------------+-+ | | | | | | ELIMINATED | | | | | | | HR| | |HR +-------------+--------------+ LC MC HC |
When middle element < search key |
When middle element > search key |
When middle element = search key |
---|
Notice how, if our probe of the region's middle element is lucky enough to find the search key there, fully half of the search space can be eliminated from further consideration. In the other two cases, only a fourth of that space can be eliminated. It is a huge advantage, in terms of minimizing the number of probes performed during a search, to be able to eliminate half of the search space, as opposed to only one-fourth.
But perhaps we can make our own luck! Suppose that instead of simply probing the middle element of the region being searched, we performed a binary search within that region in order to find a pair of adjacent locations whose values are, respectively, less than and not less then, the search key. Such a search could take place within, say, the middle row of the region. The result of such a search allows us to eliminate fully half the search space, like this:
LC c HC +-------------+-------------+ LR| | |LR | | | | ELIMINATED | | | | | | | | | +-------------+ MR| <|≥ |MR +-------------+ | | | | | | ELIMINATED | | | | | | | HR| | |HR +-------------+-------------+ LC c HC |
To clarify, here we performed a binary search within the middle row MR of the indicated region of matrix M to find c satisfying the condition that M[MR][c−1] < x and M[MR][c] ≥ x.
Having found c, fully half of the search space can be eliminated. Of course, finding c costs about lg(HC−LC+1) probes (in performing binary search upon a row of length HC−LC+1) rather than only one. An interesting question is whether performing a logarithmic number of probes to be able to eliminate half the search space results in a fewer total number of probes than does using one probe for the purpose of eliminating one-fourth of the search space.
Note: One must also allow for these possibilities:
Although one might fairly call these special cases, it is not necessarily true that they must be treated totally differently from the "normal" case.
Provided are the following Java classes, the last of which is in need of completion.
The student's task is to complete the private findAllAux() method, which is auxiliary to the public findAll() method mentioned above. The job of findAllAux() is to find, within a specified rectangular region of the resident matrix (the corners of which are described by its two parameters), all the locations containing the search key, and to add all such locations to the locList instance variable, which is of type ArrayList<GridLocation> (meaning that it contains GridLocation objects).
If gLoc is (a reference to) a GridLocation object, then the syntax by which to add it to locList is simply this:
The intent is for findAllAux() to be a recursive method. You are encouraged to have it implement the algorithm described in the A Possibly Better Approach section of this document. To aid you in this, a binarySearch() method has been included. Note that, in Java, a two-dimensional array is actually an array of one-dimensional arrays, so that, for example, if ary is of type int[][], then ary[4] is the array corresponding to row #4 of ary.
If, however, you are more comfortable in having findAllAux() implement the slightly less sophisticated algorithm described before that, that is fine.
$ java SB_Tester Welcome to the RecSaddleBackSearcher tester. Enter # rows in matrix: 9 Enter # columns in matrix: 11 Enter seed for pseudorandom # generation: 5 0 1 2 3 4 5 6 7 8 9 10 +-------------------------------------------- 0| 5 8 13 18 20 21 26 28 31 33 35 1| 9 12 17 19 24 26 28 31 32 36 37 2| 12 13 22 25 28 33 36 37 39 43 48 3| 13 17 27 29 30 36 38 42 45 48 52 4| 17 18 28 30 33 39 43 46 51 52 55 5| 18 20 33 35 38 41 47 48 55 58 63 6| 22 26 38 40 44 45 48 51 60 61 67 7| 23 31 39 44 49 53 55 57 64 66 69 8| 26 34 43 46 50 55 56 58 67 72 77 Enter a search key (or Q, or S): 20 The search for 20 involved 21 probes and yielded this list of locations: [(5,1), (0,4)] Enter a search key (or Q, or S): 73 The search for 73 involved 17 probes and yielded this list of locations: [] Enter a search key (or Q, or S): 33 The search for 33 involved 29 probes and yielded this list of locations: [(4,4), (5,2), (2,5), (0,9)] Enter a search key (or Q, or S): S 0 1 2 3 4 5 6 7 8 9 10 +-------------------------------------------- 0| 5 8 13 18 20 21 26 28 31 33 35 1| 9 12 17 19 24 26 28 31 32 36 37 2| 12 13 22 25 28 33 36 37 39 43 48 3| 13 17 27 29 30 36 38 42 45 48 52 4| 17 18 28 30 33 39 43 46 51 52 55 5| 18 20 33 35 38 41 47 48 55 58 63 6| 22 26 38 40 44 45 48 51 60 61 67 7| 23 31 39 44 49 53 55 57 64 66 69 8| 26 34 43 46 50 55 56 58 67 72 77 Enter a search key (or Q, or S): Q Goodbye from the RecSaddleBackSearcher tester. |