【问题标题】:find max square with black border找到带有黑色边框的最大正方形
【发布时间】:2016-08-29 07:46:41
【问题描述】:

对于方阵,每个单元格要么是黑色 (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

【问题讨论】:

  • @OhadEytan 不。用户似乎不相信代码有效。此外,如果您认为代码在 Stack Exchange 网络上的任何地方偏离主题,请关闭它,因为它在那里偏离主题。不是因为它可能会或可能不会在其他地方成为主题。没有将代码审查列为迁移目标是有充分理由的。
  • @Mast 我认为 OP 会对question 回答“是”“据我所知,代码是否按预期工作?” 另外,看看here 出于“充分的理由” 和那里的 cmets。
  • @OhadEytan 我用this 反驳你的链接。至于OP是否会回答是,OP应该澄清它是否有效。 Here is my code with Python 2.7, wondering if logically correct? 让我怀疑他是否验证了他得到的输出。
  • 我觉得最好能放伪代码或者解释一下解决问题的大致思路。
  • @PhamTrung,感谢您的建议。我已经用想法摘要更新了帖子。感谢您对我的代码功能问题或性能改进提出建议。

标签: python algorithm python-2.7


【解决方案1】:

这在逻辑上是不正确的,如以下简单的反例所示:

011
101
111

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

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

新算法认为两者都没有边框

0100
1111      1111
0101  or  0101
0111      0111

尽管每个都有一个 3x3 的。

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

【讨论】:

  • 感谢 j_random_hacker 指出问题,我想知道我的逻辑有什么问题?我以为我的代码已经检查了从右下角到左下角,右上角,最后到左上角。
  • 顺便说一句,我在我的代码中修复了一个问题,请参阅编辑 1 部分,我认为它在 O(n^2) 时间内是可行的,无需另一个循环。提前感谢您的进一步建议。
  • 感谢 j_random_hacker,您的输入,我的代码输出 0,我认为这是正确的值。你认为应该输出1?我测试了你左边的样本,因为它需要是一个正方形。
  • “对于您的输入,我的代码输出 0,我认为这是正确的值”——不,对于我的两个新示例来说,3 都是正确的值。如果你不再相信正确答案是 0(我猜你已经不相信了,因为你稍后会谈到“修复问题”),请删除它,否则会造成混淆。
  • 您的“Edit #2”代码将仍然错误地报告左侧我的新示例输入的 0(即,您在此代码中设置的第一个数组 A ) -- 在要求我验证正确性之前,请至少测试我已经给出的示例。为什么你认为x == y 必须坚持才能有一个正方形?
猜你喜欢
  • 2011-12-27
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
相关资源
最近更新 更多