给出了在所有三个维度中排序的三维矩阵,我们必须这样做 在其中找到一个给定的数字。
对于上述问题,我一直在想这个问题: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)
)。我是对的吗?
有没有人有任何其他想法?会有什么复杂性?
答案 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)