4

we got an increasing sorted multidimensional array for example:

int[][] mat = {{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}};

How can I use binary search to find a specific number? let's say im looking for 3.

user987339
  • 10,519
  • 8
  • 40
  • 45
D_R
  • 4,894
  • 4
  • 45
  • 62
  • 1
    Show us your attempt first – Paul Lo Dec 19 '13 at 16:21
  • I was trying to calculate the number of elements in the array using NXM then trying to find the right position on the array and use it to sort, but it didn't manage to work properly. – D_R Dec 19 '13 at 16:22
  • http://leetcode.com/2010/10/searching-2d-sorted-matrix.html – Konstantin Dec 19 '13 at 16:28
  • Can you clarify the constraints on your 'sorted multidimensional array'? For example, is the first element of row 2 required to be > than the last element of row 2, as in your sample code, or is it merely constrained to be > the first element of row 1? (in other words, is this really a sorted list broken into pieces, or is the sorting constraint on your array merely that each row and column must be sorted?) – JVMATL Dec 19 '13 at 16:32

10 Answers10

5

You can do this by translating the one-dimensional index into its two-dimensional counterpart. For example, index 0 maps to 0, 0, but index 4 will map to 1, 0, and index 15 will map to 3, 3.

This way you can use the standard binary-search algorithm, and all you have to do is to invoke the translation function when you need to look up the value at that particular index.

The formula to translate the one-dimensional index into its two-dimensional counterpart would be:

row = floor(index / columns);
column = index % columns;

This assumes that each array is sorted and that when flattened, the resulting array is also sorted.

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
2

If the multidimensional array is sorted, you could divide the binary search algorithm in two parts. First of all, you would perform the binary search to find the array inside the multidimensional one which contains the number you are looking for. And then, you perform the search inside that array.

Hope that helps.

Balduz
  • 3,560
  • 19
  • 35
1

You can use Arrays.binarySearch() for each sub array.

private static int[] binarySearch2d(int[][] arr, int toFind) {
    int[] index2d = new int[] { -1, -1 };

    // find the row
    int row = -1;
    for (int i = 0; i < arr.length; i++) {
        if (arr[i][0] > toFind) {
            break;
        }
        row = i;
    }

    if (row > -1) {
        int indexInSecond = Arrays.binarySearch(arr[row], toFind);
        if (indexInSecond > -1) {
            index2d[0] = row;
            index2d[1] = indexInSecond;
        }
    }
    return index2d;
}

private static void test() {
    int[][] mat = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
            { 13, 14, 15, 16 } };

    int[] found = binarySearch2d(mat, 12);
    int element = mat[found[0]][found[1]];
    System.out.println("Found: " + element + " at mat[" + found[0] + "]["
            + found[1] + "]");
}

will output

Found: 12 at mat[2][3]
René Link
  • 48,224
  • 13
  • 108
  • 140
  • That would have complexity of O(n/w), where `w` is the width of the array. So if you had 1000 rows of 1000 columns each, it would take on average 500 comparisons just to find the row. You're better off doing binary search on the first column to find out which row contains the element, and then binary search that row. – Jim Mischel Dec 19 '13 at 17:11
  • @JimMischel I updated my answer to first find the row – René Link Dec 19 '13 at 17:28
1

2-d array can be used as 1-d array in following way using following formula for index:-

Say you need to find kth index in 1-d array then it be element with i= k/n and j = k%n where n is order of the matrix in the 2-d array. Use binary search as in 1-d array with ending index n*n-1.

Alternative Approach:-

1.> Do binary search on first elements of each 1-D array that arr[i][0].

2.> Then using above get the 1-D array which contains the element say k then do binary search on arr[k].

Vikram Bhat
  • 6,106
  • 3
  • 20
  • 19
0

You can create an one dimensional array and use binary search .

    int[] arr = new int[]{1, 5, 6};// your converted array
    int index = Arrays.binarySearch(arr, 1);
    if (index >= 0) {
        System.out.println("found ");
    } else {
        System.out.println("not found");
    }
Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
  • what if I want it to be on O(logn) which means I cant create a one dimensional array cause it will be less efficent – D_R Dec 19 '13 at 16:23
0

You could use the first number of each array (or the last) to find the element where your number could be present and then use binary search on that element to find if it's actually there.

oli206
  • 433
  • 7
  • 17
0
public boolean Find(int[][] array, int number) { 
    int find = -1;
    for(int i = 0; i < N; i++) {
        find = binarySearch(array[i], number, 0, N);
        if(find != -1) { 
           return true; //the element is exist
        }
     }
     return false;//the element is not exist
}

Or you can revise this question it will help you a lot

Community
  • 1
  • 1
Tareq Salah
  • 3,720
  • 4
  • 34
  • 48
  • 1
    I don't like the outer trundle. The best way to do this (without getting into a total tangle with array indexing) is to run the binary search twice; on the outer then the appropriate inner dimension. So +-1 – Bathsheba Dec 19 '13 at 16:30
  • That "total tangle with array indexing" just isn't an issue. Converting a number into row/col is trivial. – Jim Mischel Dec 19 '13 at 17:14
0

You could do a binary search using just the first element of each inner array to find which row it is in. Then do a binary search inside that row to find the column.

You might need a little more logic if your matrix supports duplicates.

Ted Bigham
  • 4,237
  • 1
  • 26
  • 31
0

Use java.util.Arrays. Use Arrays.binarySearch() function on flattened matrix:

int[][] mat = {{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}};


int key = 3;
int[] oneDArray = new int[mat[0].length*mat[0].length];

int s = 0;
for(int i = 0; i < mat[0].length; i ++) 
    for(int j = 0; j < mat[0].length; j ++){                           
        oneDArray[s] = mat[i][j];
        s++;
    } 


int found = Arrays.binarySearch(oneDArray, key);
if(found > -1){
     System.out.println(found/ mat[0].length + "," + found % mat[0].length);    
}

And the demo: https://ideone.com/bFZVMs

user987339
  • 10,519
  • 8
  • 40
  • 45
0

There are different ways to define 'order' in a two-dimensional array. For the order in your example, do bin search on the first element of each row, to find the row, and then do bin search again inside the row. if the number of rows is >= than the number of columns, you can optimize doing binary search on the elements of the diagonal that starts at (0,0), then do another binary search on the rest of the row.

user3076574
  • 161
  • 5