二维数组中的二分查找

发布于 2024-10-07 09:04:37 字数 717 浏览 0 评论 0原文

我想知道,二分搜索可以应用于二维数组吗?

  • 数组的条件是什么?二维排序??
  • 它的时间复杂度是多少?
  • 该算法将如何改变搜索边界(minX,maxX,minY,maxY)?

编辑:

一维二分查找维护 2 个指针 minXmaxX.. 它选择中间索引 (minX+maxX)/2 并将其与搜索值进行比较,如果大于则更改 maxX,否则更改 minX ...直到 minX>=maxX

普通二进制 searchrh 的伪代码:

 min := 1;
  max := N; {array size: var A : array [1..N] of integer}
  repeat
    mid := min + (max - min) div 2;
    if x > A[mid] then
      min := mid + 1
    else 
      max := mid - 1;
  until (A[mid] = x) or (min > max);

谢谢

I wonder, can binary search be applied on a 2D array?

  • What would the conditions on the array be? Sorted on 2D??
  • What would be the time complexity for it?
  • How would the algorithm change the boundary of the search (minX,maxX,minY,maxY) ??

Edit:

Binary Search on 1D maintains 2 pointers minX and maxX..
It selects the middle index (minX+maxX)/2 and compare it with the search value, if greater then change maxX, else change minX... until minX>=maxX

Pseudo code for normal binary seacrh:

 min := 1;
  max := N; {array size: var A : array [1..N] of integer}
  repeat
    mid := min + (max - min) div 2;
    if x > A[mid] then
      min := mid + 1
    else 
      max := mid - 1;
  until (A[mid] = x) or (min > max);

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

一个人练习一个人 2024-10-14 09:04:37

我以简单的方式解决了这个问题,时间复杂度为 O(m + n),其中 m = no。行数,n = 行数。列数。

算法很简单:我从右上角开始(我们也可以从左下角开始),如果当前元素向左移动
大于要搜索的值,如果当前元素则为底部
小于要查找的值。

java代码如下:

public static int[] linearSearch(int[][] a, int value) {
    int i = 0, j = a[0].length - 1; // start from top right corner

    while (i < a.length && j >= 0) {
        if (a[i][j] == value) {
            return new int[]{i, j};
        } else if (a[i][j] > value) {
            j--; // move left
        } else {
            i++; // move down
        }
    }
    // element not found
    return new int[]{-1, -1};

}

Gist

您可以使用名为 改进的二进制分区

I solved it in a simple way in O(m + n) time complexity, where m = no. of rows and n = no. of columns.

The algorithm is simple: I started from top right corner (we can also start from bottom left corner) and move left if current element
is greater than the value to be searched and bottom if current element
is smaller than the value to be searched.

The java code is like:

public static int[] linearSearch(int[][] a, int value) {
    int i = 0, j = a[0].length - 1; // start from top right corner

    while (i < a.length && j >= 0) {
        if (a[i][j] == value) {
            return new int[]{i, j};
        } else if (a[i][j] > value) {
            j--; // move left
        } else {
            i++; // move down
        }
    }
    // element not found
    return new int[]{-1, -1};

}

Gist

You can further reduce the time complexity by using a method called Improved Binary Partition.

空气里的味道 2024-10-14 09:04:37

我去年考虑过这个问题......所以,我选择了这种方法:

考虑你的二维数组代表平面上的点。例如,元素 A[i][j] 表示 x = i 且 y = j 的点。为了在平面上使用二分搜索,我使用以下条件对所有点进行排序:

点 p1 < p2 当且仅当:

  • (p1 的 x 坐标) < (p2的x坐标)
  • (p1的x坐标)=(p2的x坐标)并且(p1的y坐标)<0。 (p2的y坐标)

否则p1>=p2。

现在,如果我们查看二维数组,第二行中的元素应该大于第一行中的元素。在同一行中的元素照常排序(根据其列号)。

换句话说:

  • A[i][j]> A[k][j]当且仅当(i>k)。 (不同行、同一列)
  • A[i][j]> A[i][k]当且仅当(j>k)。 (在同一行和不同列)

假设你的数组有 N 行和 M 列。现在您应该(暂时)使用以下公式将 2D 数组转换为 1D 数组(T - 临时数组):

for i:=0 to N-1 do
    for j:=0 to M-1 do
        T[i*N + j]:= A[i][j];

现在您拥有 1D 数组。按照通常的方式排序。现在您可以使用简单的二分搜索算法在其中进行搜索。

或者,您可以使用以下公式将排序后的数组转换回二维数组:

for i:=0 to N*M-1 do
    A[i div N][i - (i div N)*N]:= T[i];

并使用两种二分搜索:

一种按 x 坐标(按我们的意思是行)搜索,另一种按 y 坐标(按我们的意思按列)搜索元素在同一行。

换句话说,当您计算 mid = mid + (max - min) div 2 时,您可以将元素 A[mid][0] 与您的关键元素进行比较(在您的代码中它有 x name),当您找到包含您的元素的行时,您可以在该行中调用另一个二分搜索(A[mid]中的二分搜索)。

两种方法的复杂性:

  • 对于转换数组中的简单二分搜索:log(N*M)
  • 对于二维数组中的两次二分搜索:log(N) 对于外部搜索(在rows) + log(M) 用于内部搜索(以列为单位)。

利用对数函数的性质,我们可以简化最后一个表达式:log(N) + log(M) = log(N*M)

因此,我们证明,这两种方法具有相同的复杂性,并且使用哪一种并不重要。

但是,如果这对您来说不难,我建议您只需将数组转换为一维数组并使用简单的二分搜索(它非常简单且易于调试和检查)。

I thought about this problem last year... So, I'd choosed this approach:

Consider your 2D-array represents points in a plane. For example, your element A[i][j] represents a point with x = i and y = j. To use binary search on the plane I sort all points using this condition:

point p1 < p2 if and only if:

  • (x-coordinate of p1) < (x-coordinate of p2)
  • (x-coordinate of p1) = (x-coordinate of p2) and (y-coordinate of p1) < (y-coordinate of p2)

Othwerwise p1 >= p2.

Now, if we look to our 2D-array, elements in 2nd row should be greater than elements in 1st row. In same row elements sorted as usual (according to their column number).

In another words:

  • A[i][j] > A[k][j] if and only if (i>k). (in different rows and in same column)
  • A[i][j] > A[i][k] if and only if (j>k). (in the same row and different columns)

Consider your array has N rows and M columns. Now you should (temporarly) transform your 2D array to 1D array using this formula (T - temporary array):

for i:=0 to N-1 do
    for j:=0 to M-1 do
        T[i*N + j]:= A[i][j];

Now you have 1D array. Sort it in usual way. And now you can search in it using simple binary search algorithm.

Or you can transform your sorted array back to 2D array using this formula:

for i:=0 to N*M-1 do
    A[i div N][i - (i div N)*N]:= T[i];

And use two binary searches:

One search by x-coordinate (by rows in our meaning), another one by y-coordinate (by columns in our meaning) for elements in same row.

In another words, when you calculate mid = mid + (max - min) div 2, you can compare element A[mid][0] with your key-element(in your code it has x name) and when you find row with your element, you can call another binary search in this row (binary search in A[mid]).

Complexity for both methods:

  • for simple binary search in trasformed array: log(N*M)
  • for two binary searches in 2D array: log(N) for outer search (in rows) + log(M) for inner search (in columns).

Using the properties of logarithm function we can simplify last expression: log(N) + log(M) = log(N*M).

So, we proved, that both methods has same complexity and doesn't matter, which one to use.

But, if it's not hard to you, I suggest you simply transform your array to 1-D and use simple binary search (it's very simple and easy to debug and check).

感情废物 2024-10-14 09:04:37

二分查找以分而治之的方式工作,

int r = arr.length; // ROW Count
int c = arr[0].length; // Column Count
int start = 0; // Initialize with the 0
int end = r*c-1; // Last Index

我们将不断迭代 while 循环,每次根据要求更新开始和结束索引..
while(start <= end){

int mid = (start+end)/2;
int midX = mid/c;
int midY = mid%c;

如果当前值等于搜索元素,那么我们只需打印并返回它。

if(arr[midX][midY] == searchElement){
return true;
}

如果当前值小于搜索元素,则我们只需将中间值更新为 mid = mid + 1

if(arr[midX][midY] < searchElement){
start = mid+1;
}

如果当前值大于搜索元素,则只需将中间值更新为 mid = mid - 1

else{
end = mid-1;
}

Binary Search works in the divide and conquer way,

int r = arr.length; // ROW Count
int c = arr[0].length; // Column Count
int start = 0; // Initialize with the 0
int end = r*c-1; // Last Index

We will keep iterating the while loop, each time we updating the start and end index as per requirements..
while(start <= end){

int mid = (start+end)/2;
int midX = mid/c;
int midY = mid%c;

If the current value is equals to the search element then we just have to print and return it.

if(arr[midX][midY] == searchElement){
return true;
}

If the current value is smaller then the search element then we just have to update the mid value by mid = mid + 1

if(arr[midX][midY] < searchElement){
start = mid+1;
}

If the current value is grater than the search element then we just have to update the mid value by mid = mid - 1

else{
end = mid-1;
}
暗恋未遂 2024-10-14 09:04:37

二分查找要求对数组进行排序。反过来,排序需要数组元素上的全序关系。在一维中,很容易理解这意味着什么。我认为您必须在二维数组中定义一个一维索引,并确保数组元素沿该索引排序。

您有多种一维索引方案可供选择,基本上任何空间填充曲线都可以。我想到的显而易见的是:

  • 从第一个元素开始,沿着每一行阅读,在每行末尾转到下一行的第一个元素。
  • 同样,逐列替换。
  • 对角化,您依次读取每个对角线。

就像@Bart Kiers一样,我不明白你的第二点。

Binary search requires that your array be sorted. Sorting, in turn, requires a total ordering relationship on the array elements. In 1-D it's fairly easy to understand what this means. I think you will have to define a 1-D index into your 2-D array and ensure that the array elements are sorted along that index.

You have a variety of 1-D indexing schemes to choose from, essentially any space-filling curve will do. The obvious ones which come to mind are:

  • Start with the first element, read along each row, at the end of each row go to the first element in the next row.
  • Same, replace row by column.
  • A diagonalisation, in which you read each diagonal in turn.

Like @Bart Kiers, I don't understand your 2nd point.

随遇而安 2024-10-14 09:04:37

假设它是一个一维数组,并在分而治之时计算正确的行和列:

/**
* @param grid {[[number]]} A 2D NxM grid of numbers
* @param targetValue {number} The target value to search
* @return {[number]} A list containing the row and column. For example, [0,5] means row 0 column 5 
*/
function search (grid, targetValue) {
    let rows = grid.length;
    let cols = grid[0].length;

    let leftBound = 0;
    let rightBound = rows * cols - 1;

    while (true) {
        let currentIndex = parseInt((leftBound + rightBound) / 2);
        let currentRow = parseInt(currentIndex / cols);
        let currentColumn = currentIndex % cols;
        let currentValue = grid[currentRow][currentColumn];

        if (currentValue === targetValue) {
            return [currentRow, currentColumn];
        }
        else if (rightBound <= leftBound) {
            return [-1, -1];
        }
        else if (currentValue < targetValue) {
            leftBound = currentIndex + 1;
        }
        else {
            rightBound = currentIndex - 1;
        }
    }

}

search([[11,12,15,23],[25,28,31,32],[35,45,47,47],[50,51,55,56],[65,65,78,88]], 45);

Just pretend it's a 1D array and calculate the correct row and column as you divide and conquer:

/**
* @param grid {[[number]]} A 2D NxM grid of numbers
* @param targetValue {number} The target value to search
* @return {[number]} A list containing the row and column. For example, [0,5] means row 0 column 5 
*/
function search (grid, targetValue) {
    let rows = grid.length;
    let cols = grid[0].length;

    let leftBound = 0;
    let rightBound = rows * cols - 1;

    while (true) {
        let currentIndex = parseInt((leftBound + rightBound) / 2);
        let currentRow = parseInt(currentIndex / cols);
        let currentColumn = currentIndex % cols;
        let currentValue = grid[currentRow][currentColumn];

        if (currentValue === targetValue) {
            return [currentRow, currentColumn];
        }
        else if (rightBound <= leftBound) {
            return [-1, -1];
        }
        else if (currentValue < targetValue) {
            leftBound = currentIndex + 1;
        }
        else {
            rightBound = currentIndex - 1;
        }
    }

}

search([[11,12,15,23],[25,28,31,32],[35,45,47,47],[50,51,55,56],[65,65,78,88]], 45);
梦中的蝴蝶 2024-10-14 09:04:37

不,不可能对二维数组应用二分搜索。

二分查找的要求:

要求 1:项目已排序

在一维数组中,这意味着什么。
但这对于二维数组到底意味着什么呢?

要求 2:2 个方向

二分查找要求当您选择其中的一项时,您可以从那里进入 2 个方向。

由于排序,每当您选择一个项目时,该项目都会提供足够的信息来了解您需要在两个方向中的哪一个方向继续搜索。这允许将搜索范围分为两部分,这就是我们称之为二进制的原因。

如果您在 2D 数组中选择一个项目,则有 4 个可能的方向(甚至更多:您也可以沿对角线移动)。即使所有项目都以某种方式排序,一项中的信息也无法告诉您必须朝哪个方向以及如何根据该方向拆分数组。

仅当您可以将二维数组转换为已排序的一维数组时,才可以进行二分查找。
如果可以定义一个函数,将索引 x 和 y 组合成包含 2D 数组中所有项目的已排序虚拟一维数组的索引 i,并且可以从 i 计算回 x 和 y,那么您可以对其使用二分搜索虚拟一维阵列。该函数取决于二维数组中的项目如何排序。但这意味着您正在一维数组而不是二维数组上进行二分搜索!

No, it is not possible to apply a binary search on a 2D array.

Requirements for a binary search:

Requirement 1: Items are sorted

In a 1D array it is clear what that means.
But what does that exactly mean for a 2D array?

Requirement 2: 2 directions

A binary search requires that when ever you pick an item in it, you can go into 2 directions from there.

Because of the sorting, whenever you pick an item, the item supplies enough information to know in which of the 2 direction you need to continue your search. That allows to split the search scope in 2 parts and that's why we call it binary.

If you pick an item in a 2D array, there are 4 possible directions (or even more: you could move diagonally as well). Even if all items are sorted in someway the information in one item can't tell you which direction you have to go and how to split the array based on that.

A binary search will be possible only if you can convert the 2D array into a sorted 1D array.
If a function can be defined that combines the indexes x and y into an index i for a sorted virtual 1D array containing all items in the 2D array and x and y can be calculated back from i, then you can use a binary search on that virtual 1D array. And that function depends on how the items in the 2D array are sorted. But that means you are doing a binary search on a 1D array not on a 2D array!

腹黑女流氓 2024-10-14 09:04:37

这是二分搜索解决方案,适用于所有测试用例。

bool searchMatrix(vector<vector<int>>& matrix, int target) {
    int h = 0, w = matrix[0].size(), x;
    while(h < matrix.size() && w && (x = matrix[h][w-1]) != target) {
        if (x > target) w--;
        else h++;
    }
    return x == target;
}

This is the binary search solution and works for all test cases.

bool searchMatrix(vector<vector<int>>& matrix, int target) {
    int h = 0, w = matrix[0].size(), x;
    while(h < matrix.size() && w && (x = matrix[h][w-1]) != target) {
        if (x > target) w--;
        else h++;
    }
    return x == target;
}
柠栀 2024-10-14 09:04:37
class Solution {
  public boolean searchMatrix(int[][] matrix, int target) {
    int n = matrix.length;
    int m = matrix[0].length;
    int low =0, high=n*m-1;

    while(low <= high) {
      int mid =(low+high)/2;
      int row = mid/m;
      int col = mid%m;

      if (matrix[row][col] == target) return true;
      else if (matrix[row][col] < target) low = mid+1;
      else high = mid-1;
    }
    return false;
  }
}
class Solution {
  public boolean searchMatrix(int[][] matrix, int target) {
    int n = matrix.length;
    int m = matrix[0].length;
    int low =0, high=n*m-1;

    while(low <= high) {
      int mid =(low+high)/2;
      int row = mid/m;
      int col = mid%m;

      if (matrix[row][col] == target) return true;
      else if (matrix[row][col] < target) low = mid+1;
      else high = mid-1;
    }
    return false;
  }
}
哆兒滾 2024-10-14 09:04:37

您可以将二维数组转换为一维数组并在此处进行二分搜索。对于 mxn 数组,复杂度为 O(log(m * n))

You can transform 2D array into 1D array and do the binary search here. Complexity is O(log(m * n)) for mxn array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文