找到带黑色边框的最大方块

时间:2016-08-29 07:46:42

标签: python algorithm python-2.7

对于方阵,每个单元格为黑色(1)或白色(0),试图找到边框为黑色的最大子方格。这是我的Python 2.7代码,想知道逻辑上是否正确?任何性能改进?感谢。

我的主要想法是,跟踪顶部(连续)和左侧(连续)有多少个黑色节点,即lefttop矩阵代表。然后,基于lefttop跟踪,对于任何节点,我将尝试找到顶部和左侧连续黑色节点的最小值,然后我将基于最小值来查看正方形是否可以成立。

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

1 个答案:

答案 0 :(得分:1)

这在逻辑上是不正确的,因为以下简单的反例显示:

011
101
111

此数组不包含有边框的正方形,但您的代码报告它包含一个边长为3的正方形。您需要通过所有候选正方形尺寸的第三个嵌套循环从x开始到1(使解决方案为O(n ^ 3)-time),或者可能是一些更复杂的数据结构,使得能够更快地执行等效检查。

[编辑以解决更新的算法]

新算法认为

中没有边界正方形
0100
1111      1111
0101  or  0101
0111      0111

尽管每个人都有3x3。

停止猜测修复并思考如何将边界正方形的所有可能的位置分解成可以有效(甚至不那么有效)检查的集合。正如我在顶部试图说的那样:对于边界正方形的每个可能的右下角,您的代码目前仅检查一个矩形。但是更多的矩形可能有(i,j)作为右下角 - 它们的测试在哪里?