搜索已排序的3d数组中的元素

时间:2012-07-21 13:42:25

标签: arrays algorithm search language-agnostic

  

给出了在所有三个维度中排序的三维矩阵,我们必须这样做   在其中找到一个给定的数字。

对于上述问题,我一直在想这个问题:3D数组arr[m][n][r]就像一堆矩形,每个矩形(考虑arr[m][n][0])的最大元素是最右边的 - 大多数元素(arr[m-1][n-1][0])。我们可以在O(m+n)

中的每个矩形内搜索
int row = 0;
int col = N-1;

while (row < M && col >= 0) 
{
  if (mat[row][col] == elem) 
  { 
    return true;
  }
  else if (mat[row][col] > elem) 
  { 
    col--;
  } 
  else 
  { 
    row++;
  } 
}

我认为它可以类似地扩展到第三维,因此使其成为线性复杂性解决方案(O(m+n+r))。我是对的吗?

有没有人有任何其他想法?会有什么复杂性?

3 个答案:

答案 0 :(得分:4)

您不能将线性复杂度2D解决方案扩展到第三维,从而使O(m + n + r)解决方案脱离其中。在每个方向上独立分类的3D阵列包含O(N 2 )元素的组,这些元素彼此之间没有排序。例如,子arr[i][j][k],其中i+j+k = (m+n+r)/2完全未排序。因此,您必须检查此类子数组的每个元素以查找给定的数字。这证明你不能发明一种复杂度优于O(N 2 )的算法(至少当m,n和r彼此差别不大时)。这只是this answer的证明的扩展。

以下是一个例子:

k=0: |1 x|   k=1: |z 3|
     |y 3|        |3 4|

此数组按所有3个维度排序。但这并不能确定元素x,y,z的任何排序顺序。您可以将(1,3)范围内的任何值分配给这些元素。在搜索值为“2”的元素时,您必须检查所有这些“未排序”的值(x和y和z)。如果增加数组的大小,您会看到“未排序”值的数量可能会以二次方式增加。这意味着搜索算法的最坏情况时间复杂度也应该以二次方式增加。

你可以找到最小的数组大小(让它为'r'),并为每个矩阵arr[*][*][k]搜索O(m + n)时间内的给定数字,得到O((m + n)* r)时间复杂度。

或者,如果其中一个数组大小比其他数组(r >> m*n)大得多,则可以在arr[i][j][*]中使用二进制搜索(对于每个i,j),这将得到O(m n log(r))时间复杂度。

答案 1 :(得分:1)

如果内存消耗不是一个大问题,你可以将你的数组复制到单个1D数组中,然后按值对这个数组进行排序,并用O(log(n + m + r)在其中执行二进制搜索)复杂性。但是初始排序需要O((n + m + r)* log(n + m + r)),这将定义总算法复杂度。

我认为感谢3D数组在每个维度中排序的事实,可以找到一些算法,将其转换为排序的1D阵列比O((n + m + r)* log(n + m +)更快r)),但我不知道这些事情。也许Chiyou试图解释这个。

答案 2 :(得分:1)

从理论上讲,我可以想到一个递归的解决方案。

假设n是您在立方体NxNxN中寻找的数字。这个立方体从东到西,从北到南,从上到下按升序排序。这样东北顶极端的数量最小,最南 - 西 - 底的数量最大。

选择多维数据集中心的数字。 如果这个数字等于n,那么我们找到了这个数字。 如果这个数字大于n,我们可以忽略位于西南 - 底部的所有数字,因为它们都将大于n。这些数字是立方体的1/8。 现在,我们可以轻松地将立方体的剩余部分分成7个立方体并重复该过程。

如果此数字小于n,我们可以忽略所有位于东北顶的数字。

Point find(int[][][]matrix, int N, int n)
{
    if(N == 0)
    {
      return null;
    }

    int x = matrix[N/2][N/2][N/2];
    if( x == n)
        return new Point(N/2, N/2, N/2);
    else if (x > n)
    {
        for(Matrix m: SplitTheCubeInto8CubesAndIgnoreSouthWestBottomCube(matrix))
        {
            if((p = find(m, N/8, n)) != null)
                return p;
           else
                return p;
        }
    }
    else
    { 
        for(Matrix m: SplitTheCubeInto8CubesAndIgnoreNorthEastTopCube(matrix))
        {
            if((p = find(m, N/8, n)) != null)
                return p;
           else
                return p;
        }
    }
}

复杂性可表示如下: T(M)= 7 * T(M / 8)+ 1(M是立方体中的总点数.M = N * N * N.在每次比较中,我们留下7个M / 8的立方体每个尺寸) O = ln(M)[ln基于8/7] 或者O = ln(N)