对于方阵,每个单元格为黑色(1)或白色(0),试图找到边框为黑色的最大子方格。这是我的Python 2.7代码,想知道逻辑上是否正确?任何性能改进?感谢。
我的主要想法是,跟踪顶部(连续)和左侧(连续)有多少个黑色节点,即left
和top
矩阵代表。然后,基于left
和top
跟踪,对于任何节点,我将尝试找到顶部和左侧连续黑色节点的最小值,然后我将基于最小值来查看正方形是否可以成立。
A=[[1,1,0,0,0],
[1,1,1,1,1],
[0,0,1,0,1],
[0,0,1,1,1],
[0,0,0,0,0]]
top=[[0] * len(A[0]) for i in range(len(A))]
left=[[0] * len(A[0]) for i in range(len(A))]
result = 0
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i-1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j-1] + 1 if j > 0 else 1
print top
print left
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i-1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j-1] + 1 if j > 0 else 1
x = min(top[i][j], left[i][j])
if x > 1:
y = min(left[i-x+1][j], top[i][j-x+1])
result = max(result, y)
print result
编辑1 ,修复了j_random_hacker指出的问题。
A = [[1, 1, 0, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 0]]
A = [[0,1,1],
[1,0,1],
[1,1,1]]
top = [[0] * len(A[0]) for i in range(len(A))]
left = [[0] * len(A[0]) for i in range(len(A))]
result = 0
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
print top
print left
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
x = min(top[i][j], left[i][j])
if x > 1:
y = min(left[i - x + 1][j], top[i][j - x + 1])
if x == y:
result = max(result, y)
print result
编辑2 ,通过j_random_hacker解决问题。
A = [[0,1,0,0],
[1,1,1,1],
[0,1,0,1],
[0,1,1,1]]
A = [[0,1,1],
[1,0,1],
[1,1,1]]
A = [[1, 1, 0, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 0]]
top = [[0] * len(A[0]) for i in range(len(A))]
left = [[0] * len(A[0]) for i in range(len(A))]
result = 0
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
print top
print left
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
x = min(top[i][j], left[i][j])
while x > 1:
y = min(left[i - x + 1][j], top[i][j - x + 1])
if x == y:
result = max(result, y)
break
x -= 1
print result
编辑3 ,新修复
A = [[0,1,0,0],
[1,1,1,1],
[0,1,0,1],
[0,1,1,1]]
A = [[1, 1, 0, 0, 0],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 0]]
A = [[0,1,1],
[1,0,1],
[1,1,1]]
top = [[0] * len(A[0]) for i in range(len(A))]
left = [[0] * len(A[0]) for i in range(len(A))]
result = 0
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
print top
print left
for i in range(len(A)):
for j in range(len(A[0])):
if A[i][j] == 1:
top[i][j] = top[i - 1][j] + 1 if i > 0 else 1
left[i][j] = left[i][j - 1] + 1 if j > 0 else 1
x = min(top[i][j], left[i][j])
while x > 1:
y = min(left[i - x + 1][j], top[i][j - x + 1])
if x <= y:
result = max(result, x)
break
x -= 1
print result
答案 0 :(得分:1)
这在逻辑上是不正确的,因为以下简单的反例显示:
011
101
111
此数组不包含有边框的正方形,但您的代码报告它包含一个边长为3的正方形。您需要通过所有候选正方形尺寸的第三个嵌套循环从x
开始到1(使解决方案为O(n ^ 3)-time),或者可能是一些更复杂的数据结构,使得能够更快地执行等效检查。
[编辑以解决更新的算法]
新算法认为
中没有边界正方形0100
1111 1111
0101 or 0101
0111 0111
尽管每个人都有3x3。
停止猜测修复并思考如何将边界正方形的所有可能的位置分解成可以有效(甚至不那么有效)检查的集合。正如我在顶部试图说的那样:对于边界正方形的每个可能的右下角,您的代码目前仅检查一个矩形。但是更多的矩形可能有(i,j)作为右下角 - 它们的测试在哪里?