在方阵中,每个单元格都是黑色或白色。设计一种算法来找到最大子方格,使所有 4 个边框均为黑色
给定一个方阵,其中每个单元格都是黑色或白色。设计一种算法来找到最大子方格,使所有 4 个边框均为黑色。
我有 O(n^2) 算法:
从左到右扫描每一列,对于每列中的每个单元格,扫描每一行以找到带有后边框的最大子方块。
有更好的解决方案吗?
谢谢
Given a square matrix, where each cell is black or white. Design an algorithm to find the max sub-square such that all 4 borders are black.
I have O(n^2) algorithm:
Scan each column from left to right, for each cell in each column, scan each row to find the max sub-square with back borders.
Are there better solutions ?
thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
C++ 代码:
C++ Code:
我不知道为什么你可以得到 O(n^2) 算法。从数学上来说,这是不可能的。
假设您有一个 NxN 矩阵。您需要检查:
1. 1个矩阵大小:NxN,
2. 2*2矩阵,大小:(N-1)x(N-1),
3. 3*3矩阵,大小:(N-2)x(N-2),
....
总共,您必须检查:1+ 2^2 + 3^2 + ... + N^2 = N(N+1)(2N+1)/6。
所以任何算法都不能比 O(N^3) 做得更好
I don't know why you can get an O(n^2) algorithm. Mathematically, it is impossible.
Let's say you have an NxN matrix. You need to check:
1. 1 matrix of size: NxN,
2. 2*2 matrices of size: (N-1)x(N-1),
3. 3*3 matrices of size: (N-2)x(N-2),
....
In total, you have to check: 1+ 2^2 + 3^2 + ... + N^2 = N(N+1)(2N+1)/6.
So any algorithm cannot do better than O(N^3)
O(n^2) 是可能的。我想这是最佳的,因为你有 n^2 个单元格。
请注意,任何正方形的左上角和右下角都位于同一条对角线上。
现在,如果我们可以在 O(n) 时间内处理每个对角线,我们就会有一个 O(n^2) 时间算法。
假设我们有一个左上角的候选者。我们可以计算其下方和右侧的连续黑色单元的数量,并取两者中的最小值并将其称为 T。
对于右下候选,我们可以计算其左侧的连续黑色单元的数量。到顶部并取两者中的最小值,称之为 B。
一旦我们有了两个数字 T 和 B,我们就可以判断给定的左上角、右下角候选是否实际上给了我们一个全黑的正方形边界。
现在,通过对整个矩阵进行四次遍历,可以在 O(n^2) 时间内计算每个单元格的这两个数字(如何?)。
那么让我们假设已经完成了。
现在考虑对角线。我们的目标是在 O(n) 时间内沿着这条对角线找到左上、右下对。
假设我们在数组 T[1...m] 中计算了 T,其中 m 是对角线的长度。类似地,我们有一个数组 B[1...m]。 T[1] 对应对角线的左上角,T[m] 对应对角线的右下角。与 B 类似。
现在我们按如下方式处理对角线,对于每个左上候选 i,我们尝试找到一个右下候选 j,它将给出最大的平方。请注意,j >= i。另请注意,如果 (i,j) 是候选者,则 (i',j) 不是,其中 i' > 。我。
请注意,如果
T[i] >= j-i+1
且B[j] >= j-i+1
,则 i 和 j 形成一个正方形。即
T[i] +i - 1 >= j
和B[j] -j - 1 >= -i
。因此,我们形成新的数组,例如
TL[k] = T[k] + k -1
和BR[k] = B[k] -k - 1
。因此,给定两个新数组 TL 和 BR 以及一个 i,我们需要回答以下查询:
现在假设我们能够处理范围最大查询的 BR(可以在 O(m) 时间内完成)。
现在给定 TL[i],在 [i, TL[i]] 范围内,我们找到 BR 的最大值,即 BR[j1]。
现在如果 BR[j1] >= -i,我们找到 [j1, TL[i]] 范围内 BR 的最大值并继续这样。
一旦我们找到 (TL[i],BR[j]) 候选者,我们就可以忽略未来 i 的数组 BR[1...j]。
这使我们能够在 O(n) 时间内处理每个对角线,从而给出 O(n^2) 总算法。
我省略了很多细节并给出了草图,因为它已经太长了。请随意编辑此内容并进行澄清。
唷。
O(n^2) is possible. I guess it is optimal, as you have n^2 cells.
Notice that the top-left corner and the bottom-right corner of any square lie along the same diagonal.
Now if we could process each diagonal in O(n) time, we would have an O(n^2) time algorithm.
Say we have a candidate for a top-left corner. We can compute the number of continuous black cells below it, and to the right of it and take the minimum of the two and call it T.
For a bottom-right candidate, we can compute the number of continuous black cells to the left of it, and to the top and take the minimum of the two, call it B.
Once we have the two numbers T and B, we can tell if the given top-left, bottom-right candidate actually give us a square with all black borders.
Now those two numbers can be computed for each cell, in O(n^2) time by making four passes through the whole matrix (How?).
So let us assume that is done.
Now consider a diagonal. Our aim is to find a top-left,bottom-right pair along this diagonal in O(n) time.
Let us assume we have the T's computed in an array T[1...m] where m is the length of the diagonal. Similarly we have an array B[1...m]. T[1] corresponds to the top-left end of the diagonal and T[m] to the bottom-right. Similarly with B.
Now we process the diagonal as follows, for each top-left candidate i, we try to find a bottom-right candidate j which will give the largest square. Notice that j >= i. Also notice that if (i,j) is a candidate, then (i',j) isn't, where i' > i.
Note that i and j form a square if
T[i] >= j-i+1
andB[j] >= j-i+1
.i.e.
T[i] +i - 1 >= j
andB[j] -j - 1 >= -i
.So we form new arrays such that
TL[k] = T[k] + k -1
andBR[k] = B[k] -k - 1
.So given the two new arrays TL and BR, and an i, we need to answer the following queries:
Now suppose we were able to process BR for range maximum queries (can be done in O(m) time).
Now given TL[i], in the range [i, TL[i]] we find the maximum value of BR, say BR[j1].
Now if BR[j1] >= -i, we find the maximum of BR in the range [j1, TL[i]] and continue this way.
Once we find the (TL[i],BR[j]) candidate, we can ignore the array BR[1...j] for future i.
This allows us to process each diagonal in O(n) time, giving an O(n^2) total algorithm.
I have left out a lot of details and given a sketch, as it was already too long. Feel free to edit this with clarifications.
Phew.