搜索已排序的2D矩阵

时间:2010-07-23 07:46:56

标签: algorithm data-structures sorting matrix

M是整数的二维矩阵(nXm) 它们按行和列排序 编写函数搜索(int s),返回数字或Null的确切位置。 最有效的方法是什么?

4 个答案:

答案 0 :(得分:14)

init:m [1..n(行),1 .... m(列)]

i = N时,J = 1

从(i,j)开始:

STEP 1) if the value equals m(i,j) return (i,j)
STEP 2) if the value > m(i,j) go to step 1 with j+=1
STEP 3) else go to step 1 with i-=1
如果j或i超出范围,则在每一步

返回no-solution。

在n = m的情况下,该解决方案的复杂性为O(n + m),复杂度为O(n)

我想知道是否存在二进制搜索中的log(n * m)解决方案

编辑另一种可能的解决方案:

STEP 1)take the middle (n/2,m/2) of the matrix and compare it to the value
STEP 2) if the value equals m(i,j) return (i,j)
STEP 3) if the value is higher you can get rid from the first quarter  
STEP 4) if the value is lower you can get rid from the forth quarter
STEP 5) split the 3 other quarters to 2, a rectangle and a box, 
        send those both items to step 1 in a recursive manner

我不确定此解决方案的效率: 若R = N * M则T(R)= T(R / 2)+ T(R / 4)+ O(1)

答案 1 :(得分:1)

说我们有

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

现在我们搜索6.您可以看到从右上角(5 7)到左下角(5 6 7)有一个“条带”,其中小于6的值翻转到大于6的值(“条带” “标有*):

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

所以算法是:

  • 检查左上角是否更大 - > return null
  • 检查右下角是否小于您的号码 - > return null
  • 从左上角向右下角,直到找到“条带”
  • 沿两个方向跟随地带,直至找到号码。

答案 2 :(得分:1)

考虑以下输入:

1 2 3

4 5 6

7 8 9

例如DuduAlul的算法找不到数字4的位置。

答案 3 :(得分:0)

我刚打开记事本并写了一下,但我认为这将在O(x)时间内完成,其中x是n和m之间的较大索引。此算法的最坏情况是搜索项等于数组中的最大项,此方法将循环遍历n或m(以较大者为准)次。如果这种情况很常见,可以从右下角而不是左上角开始,然后减少指数而不是增加它们。

int[] SearchArray(int s, int[][] array)
{
    int i = 0;
    int j = 0;
    int n = array.GetLength(0);
    int m = array.GetLength(1);
    if (s > array[n][m])
            return null;
    while (i < n && j < m)
    {
        if (array[i][j] > s)
            return null;
        if (array[i][j] == s)
            return new int[]{i,j};
        try
        {
            if (array[i+1][j+1] < s)
            {
                    i++;
                    j++;
            }
            else if (array[i+1][j] > array[i][j+1])
                if (array[i+1][j] < s)
                    i++;
                else
                    j++;
            else if (array[i][j+1] > array[i+1][j])
                if (array[i][j+1] < s)
                    j++;
                else
                    i++;
            else if (array[i+1][j] == array[i][j+1])
                if (n < m)
                    i++;
                else
                    j++;
        }
        catch(IndexOutOfRangeException e)
        {
            if (i == n-1)
                j++;
            if (k == m-1)
                i++;
        }
    }
}

编辑优化和格式化