给定方阵,每个单元格为黑色或白色。设计算法以找到最大子方块,使得所有4个边界都是黑色的。
我有O(n ^ 2)算法:
从左到右扫描每列,对于每列中的每个单元格,扫描每一行以查找带有后边框的最大子正方形。
有更好的解决方案吗?
感谢
答案 0 :(得分:5)
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'和gt;岛
请注意,如果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,我们需要回答以下问题:
最大的j是什么,TL [i]> = j和BR [j]> = -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)总算法。
我遗漏了很多细节并给出了草图,因为它已经太长了。请随意修改此内容。
呼。
答案 1 :(得分:0)
C ++代码:
#include<iostream>
using namespace std;
int min(int a,int b,int c)
{
int min = a;
if(min > b)
min = b;
if(min > c)
min = c;
return min;
}
int main()
{
const int size = 5;
char a[size][size] = { {'b','b','b','b','w'},{'b','b','b','b','b'},{'b','b','b','b','b'},{'b','b','w','b','b'},{'b','w','w','b','b'} };
int arr[size+1][size+1];
// First row and First column of arr is zero.
for(int i=0;i<size+1;i++)
{
arr[0][i] = 0;
arr[i][0] = 0;
}
int answer = 0;
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
if(a[i][j] == 'w')
arr[i+1][j+1] = 0;
if(a[i][j] == 'b')
{
int minimum = min(arr[i][i],arr[i+1][j],arr[i][j+1]);
arr[i+1][j+1] = minimum + 1;
if( arr[i+1][j+1] > answer)
answer = arr[i+1][j+1];
}
}
}
for(int i=0;i<size+1;i++)
{
for(int j=0;j<size+1;j++)
{
cout<<arr[i][j]<<"\t";
}
cout<<endl;
}
cout<<answer<<endl;
return 0;
}
答案 2 :(得分:0)
/* In 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. The right Java implementation based on a previous post.
*/
public int maxSubsquare(boolean[][] M){
int n = M.length;
maxsize=0;
checkDiag(M, 0, 0, n);
for (int i=1; i<n; i++){
checkDiag(M, i, 0, n);
checkDiag(M, 0, i, n);
}
return maxsize;
}
int maxsize;
void checkDiag(boolean[][] M, int i, int j, int n){
if (i>=n-maxsize || j>=n-maxsize) return;
int step = 0;
while (step<(n-Math.max(i, j))&& M[i][j+step]&&M[i+step][j]){
int s = step;
while (s>0){
if (M[i+s][j+step]&&M[i+step][j+s]) s--;
else break;
}
if (s==0)
maxsize = Math.max(maxsize, step+1);
step++;
}
if (step==0) checkDiag(M, i+step+1, j+step+1, n);
else checkDiag(M, i+step, j+step, n);
}
答案 3 :(得分:0)
我不知道为什么你可以得到一个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)做得更好