【问题标题】:Rectangular region in an array数组中的矩形区域
【发布时间】:2011-04-14 02:20:54
【问题描述】:

给定一个包含 1 和 0 的 N*N 矩阵并给定一个整数 k,找到一个包含 k 个 1 的矩形区域的最佳方法是什么?

【问题讨论】:

  • 有趣的问题。您是否只寻找一个地区? N 和 k 通常有多大,1 和 0 的概率分布是多少?算法需要多快?我猜你不知道答案,因为这是一个面试问题,但这就是我要问的。
  • 了解更多信息非常重要。如果 p 是 1 的概率,并且 k / p 远小于 N,那么 最简单 的方法就是尝试单行或单列。取一个 1xk 区域,计算一个的数量,然后将单元格添加到最后,直到你有 k 个。如果 k /p 远小于 N,则这很有可能起作用。当然,如果一排不符合要求,你可以继续下一个……毕竟你有 N 个。但无论如何,什么是“最好的”?最好的最坏情况时间?最佳平均案件时间?最小的结果矩形区域?
  • 这里有一个类似的问题:stackoverflow.com/questions/1726632/…
  • 是的...这就是我要找的...
  • 对于满足要求的any矩形,可以从第一行开始,直到找到1,然后尝试下一行,直到找到另一个1,然后继续尝试第一行的剩余元素......同时递减 k 并依次耗尽每一行。这样,您肯定会得到一个矩形 :-) 但我无法说这是 best 方法 - 这取决于“最佳”的衡量标准!我显然也在考虑矩阵类型的操作(那里只熟悉 Ruby 和 Python)。

标签: algorithm puzzle


【解决方案1】:

我可以用 O(N^3*log(N)) 做到这一点,但肯定最好的解决方案更快。首先,您创建另一个 N*N 矩阵 B(初始矩阵为 A)。 B的逻辑如下:

B[i][j] - is the number of ones on rectangle in A with corners (0,0) and (i,j).

您可以通过动态规划为 O(N^2) 计算 B:B[i][j] = B[i-1][j] + B[i][j-1] - B[i- 1][j-1] + A[i][j].

现在很容易用 O(N^4) 来解决这个问题,方法是遍历所有右下 (i=1..N, j=1..N, O(N^2)), left -bottom (z=1..j, O(N)) 和 right-upper (t=1..i, O(N)),你可以在 B 的帮助下得到这个矩形中的个数:

sum_of_ones = B[i][j] - B[i][z-1] - B[t-1][j] + B[t-1][z-1].

如果你得到了准确的 k: k==sum_of_ones,那么就得出结果。

要使它成为 N^3*log(N),你应该通过二分搜索找到右上(所以不只是迭代所有可能的单元格)。

【讨论】:

    【解决方案2】:

    考虑这个更简单的问题:

    给定一个大小为 N 且仅包含值 1 和 0 的向量,找出其中恰好包含 k 个值 1 的子序列。

    A 为给定向量,S[i] = A[1] + A[2] + A[3] + ... + A[i] 表示子序列A[1..i] 中有多少个1。

    对于每个i,我们对j <= i 的存在感兴趣,这样S[i] - S[j-1] == k

    我们可以使用以下关系在O(n) 中使用哈希表找到它:

    S[i] - S[j-1] == k => S[j-1] = S[i] - k

    let H = an empty hash table
    for i = 1 to N do
      if H.Contains (S[i] - k) then your sequence ends at i
      else
        H.Add(S[i])
    

    现在我们可以使用它来解决O(N^3) 中的给定问题:对于给定矩阵中的每个行序列(有O(N^2) 行序列),考虑该序列表示一个向量并应用前面的算法在上面。 S 的计算在矩阵情况下有点困难,但并不难弄清楚。如果您需要更多详细信息,请告诉我。

    更新: 假设k = 12

    0 1 1 1 1 0
    0 1 1 1 1 0
    0 1 1 1 1 0
    

    单独考虑第一行:

    0 1 1 1 1 0
    

    将其视为向量0 1 1 1 1 0 并对其应用更简单问题的算法:我们发现没有子序列加起来为 12,因此我们继续。

    考虑前两行:

    0 1 1 1 1 0
    0 1 1 1 1 0
    

    将它们视为向量0+0 1+1 1+1 1+1 1+1 0+0 = 0 2 2 2 2 0,然后将算法应用于更简单的问题:同样,没有子序列加起来为 12,所以继续。

    考虑前三行:

    0 1 1 1 1 0
    0 1 1 1 1 0
    0 1 1 1 1 0
    

    将它们视为向量0 3 3 3 3 0 并对其应用更简单问题的算法:我们发现从位置 2 开始到位置 5 结束的序列是解决方案。由此我们可以通过简单的簿记得到整个矩形。

    【讨论】:

    • “给定矩阵中的行序列”是什么意思?
    • @Yassin Ezbakhe - 我的意思是连续的行序列。考虑一个有 5 行编号为 1 到 5 的矩阵。第 2、3 和 4 行形成一个行序列。将这些行视为向量(这些行的列是向量的元素)并将算法应用于更简单的问题。由于有O(N^2)这样的行序列,而更简单问题的算法是O(N),并且必须应用于所有行序列,因此解决方案的总复杂度是三次。
    • 如果你有矩阵 [[0,1,1,1,1,0],[0,1,1,1,1,0],[0,1,1,1 ,1,0]],你将如何提取 3x4 全为矩形?
    • @Yassin Ezbakhe - 我已经在我的原始帖子中使用了这个例子。
    • @IVlad: 如果你有矩阵 [[0, 1, 1, 1, 0], [1, 1, 1, 1, 1]] 怎么办?对于 k = 8,即使没有解决方案,您的算法也会给出解决方案。而且,您还必须将 k 从 N^2 迭代到 0 才能找到解决方案,这会将最坏情况的成本提高到 O(N^5)。
    猜你喜欢
    • 1970-01-01
    • 2011-05-01
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    相关资源
    最近更新 更多