【问题标题】:Find greatest X shape in a binary matrix在二进制矩阵中找到最大的 X 形状
【发布时间】:2017-06-28 05:09:10
【问题描述】:

我最近对一家公司进行了技术测试,我认为他们遇到了一个非常有趣的问题,即识别二进制矩阵中的形状。

本练习的目标是创建一种算法,该算法可以在二进制矩阵中找到最大的 X 形状并返回其长度。 X 是这样定义的: -A X 由两条等长的对角线组成,它们共享一个独特的点。 例如:

101
010
101

包含长度为 3 的有效 X,因此算法将返回 3。

1001
0110
0110
1001

不包含任何有效的 X,因此算法将返回 1,因为长度为 1 的 X 是单个 1。

我设法完成了这个练习,但我实现了一个非常混乱的算法,时间复杂度估计为 O(n3),这很糟糕,不适合非常大的矩阵。这种复杂性的很大一部分是我用来遍历矩阵的双 for 循环。

我可以做些什么来制作更简洁的算法?我问这个问题是出于个人兴趣,需要提高我的技能和实践思维。

【问题讨论】:

  • X 是否需要用零“勾勒”?或者(例如)是否将所有 1 的数组视为具有跨越整个网格的 X?
  • @ruakh 不需要用 0 来勾勒,只要满足 2 等于对角线共享一个唯一点的条件即可。
  • 顺便说一下,我认为最干净的算法是O(n^3)。不要把“乱”和“慢”混为一谈!
  • 我实际上经历了几次迭代,而且我现在的迭代速度有点快,我相信!长话短说,我检查了数组中的每个元素,当我找到一个 1 时,我尝试检查我可以将它的对角线扩展多少以检查可能的最大 X。
  • 对角线相等的要求意味着两条对角线的长度相同,并且共享一个唯一的 1。为了清楚起见,我编辑了第一篇文章!

标签: algorithm matrix


【解决方案1】:

如果您对 O(n^2) 额外空间感到满意,那么一种选择是构建两个额外的数组:一个记录以每个单元格为中心的最长 \ 形状的长度,一个记录长度最长的/。 (您可以通过使用三重嵌套循环在 O(n^2) 时间内构建每个 - 这可能听起来像 O(n^3) 时间,但记忆意味着您只需要迭代 once 在任何给定的\/ 上,因此最里面的循环可以是摊销常数时间。)然后您遍历所有位置;对于任何位置,以该位置为中心的最大X 的大小等于该位置的两个矩阵值中较小的那个。只需跟踪最大的这样较小的值,就完成了。

这具有 O(n^2) 的最坏情况时间复杂度,这显然是渐近最优的。

【讨论】:

  • 其实多出一个数组就够了,可以把另一个方向的扫描和上一步结合起来。
  • @Henry:这是一个很好的观点。那仍然是 O(n^2) 额外空间;但是如果输入是一个整数数组,并且我们可以(暂时)改变它的内容,那么我们实际上可以将输入数组本身用作“额外”数组之一。加上您的建议,这将消除对额外空间的任何需求(除了用于局部变量的 O(1) 空间等)。
【解决方案2】:

虽然问题中没有明确指定,但我假设两条对角线的公共点必须在中间才能形成有效的“X”形状。图片似乎支持这一假设。

想象一下阵列旋转了 45 度,这样我们现在就有了某种菱形。我们现在正在搜索与 x 和 y 轴对齐的十字。

您可以逐行检查跨度。只有具有奇数个 1 的跨度可能是十字的一部分(否则没有中间元素)。

对于每个这样的跨度,检查是否真的有一个十字架。

如果我们只对最大尺寸感兴趣,您可以省略交叉检查跨度是否小于或等于目前找到的最大值。

识别水平跨度所需的时间是 O(n^2)。 对于长度为 m 的每个水平跨度,您最多检查另一个方向的 m+2 个元素。所有 span 的长度之和显然是 O(n^2),因此交叉检查所需的时间也是 O(n^2)。

因此,该算法的总工作量为 O(n^2),并且不需要额外的空间。

【讨论】:

  • 只有奇数个span才可能是叉的一部分(否则没有中间元素)。 X的定义 这里似乎不需要对角线在中间相遇,只是在一个共同点。这可能值得在问题或您的答案中澄清。
  • @Patrick87 你是对的,重新阅读问题的确切措辞似乎也允许“V”形。我会补充一句。
  • 我同意,这在测试中没有指定,所以我不确定它是否也应该允许不均匀的 X。那个问题不是很清楚。
【解决方案3】:

这是一个O(m*n) 过程,其中m 是矩阵中的行数,n 是矩阵中的列数:

从上到下逐行迭代一次。每个1 可以有零到两个父母。如果1 有父级,则为其分配其父级的父级。与两个父母一起保存细胞。现在对“孩子”做同样的事情,从下到上遍历行。之后,找到显示最大 X 的具有两个父母和两个孩子的单元格。

10001
01010
00100
01010
10001

从上到下:

p1   ...   p2
  p1 ... p2
   [p1,p2] // one cell with two parents
...
...

自下而上:

...
...
   [c1,c2]
  c1 ... c2
c1   ...   c2

【讨论】:

    【解决方案4】:

    O(n) 空间和 O(n) 时间(对于 n 单元格的数量):

    1. 在 O(n) 时间内,将矩阵的每个元素与沿直线 NE、SE、SW 和 NW 中的“1”个单元格的最大距离相关联(像地图一样读取矩阵)。

    2. 在 O(n) 时间内,找到这四个值中最小值为 '1' 的单元格。您可以在设置四个中的最后一个的同时执行此操作。

    3. 最大长度是上面找到的最大最小长度的两倍多。

    【讨论】:

    • 为了说明为什么第 1 步是 O(n):假设我们要填充 SE 值。矩阵 S 和 E 侧的每个单元格的 SE_val = 0,然后从 S 和 E 边缘一次进入一行/列,每个单元格获得 SE_val = 0(如果到 SE 的单元格为 0)或 1 + 单元格的 SE_val 到 SE。这会在每个方向上查看每个单元格一次。这可以进一步优化,但仍然是 O(n)。
    猜你喜欢
    • 1970-01-01
    • 2021-11-03
    相关资源
    最近更新 更多