数组中的矩形区域
给定一个 N*N 矩阵,其中包含 1 和 0,并且给定一个整数 k,找到其中包含 k 个 1 的矩形区域的最佳方法是什么???
Given an N*N matrix having 1's an 0's in them and given an integer k,what is the best method to find a rectangular region such that it has k 1's in it ???
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我可以用 O(N^3*log(N)) 来完成,但肯定最好的解决方案更快。首先创建另一个 N*N 矩阵 B(初始矩阵是 A)。 B 的逻辑如下:
您可以通过动态规划以 O(N^2) 计算 B: B[i][j] = B[i-1][j] + B[i][j-1] - B[i-1][j-1] + A[i][j]。
现在,通过迭代所有右下 (i=1..N, j=1..N, O(N^2))、左下 ( z=1..j, O(N)) 和右上 (t=1..i, O(N)) 并在 B 的帮助下得到这个矩形中 1 的数量:
如果你正好得到k: k==sum_of_ones,然后输出结果。
为了使其成为 N^3*log(N),您应该通过二分搜索找到右上(所以不仅仅是迭代所有可能的单元格)。
I can do it with O(N^3*log(N)), but sure the best solution is faster. First you create another N*N matrix B (the initial matrix is A). The logic of B is the following:
You can evaluate B for O(N^2) by dynamic programming: B[i][j] = B[i-1][j] + B[i][j-1] - B[i-1][j-1] + A[i][j].
Now it is very easy to solve this problem with O(N^4) by iterating over all right-bottom (i=1..N, j=1..N, O(N^2)), left-bottom (z=1..j, O(N)), and right-upper (t=1..i, O(N)) and you get the number of ones in this rectangular with the help of B:
If you got exactly k: k==sum_of_ones, then out the result.
To make it N^3*log(N), you should find right-upper by binary search (so not just iterate all possible cells).
考虑这个更简单的问题:
令
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
现在我们可以用它来解决
O(N^3)
中给定的问题:对于给定的每个行序列矩阵(有O(N^2)
行序列),考虑该序列来表示向量并对其应用之前的算法。在矩阵情况下,S
的计算有点困难,但并不难算出来。如果您需要更多详细信息,请告诉我。更新:
以下是该算法如何处理以下矩阵,假设
k = 12
:单独考虑第一行:
将其视为向量
0 1 1 1 1 0
并应用更简单问题的算法:我们发现没有子序列加起来等于 12,所以我们继续。考虑前两行:
将它们视为向量
0+0 1+1 1+1 1+1 1+1 0+0 = 0 2 2 2 2 0
并应用算法更简单的问题:同样,没有子序列加起来等于 12,所以继续。考虑前三行:
将它们视为向量
0 3 3 3 3 0
并对其应用更简单问题的算法:我们找到从位置 2 开始并在位置 5 结束的序列成为解决方案。由此我们可以通过简单的记账得到整个矩形。Consider this simpler problem:
Let
A
be the given vector andS[i] = A[1] + A[2] + A[3] + ... + A[i]
, meaning how many 1s there are in the subsequenceA[1..i]
.For each
i
, we are interested in the existence of aj <= i
such thatS[i] - S[j-1] == k
.We can find this in
O(n)
with a hash table by using the following relation:S[i] - S[j-1] == k => S[j-1] = S[i] - k
Now we can use this to solve your given problem in
O(N^3)
: for each sequence of rows in your given matrix (there areO(N^2)
sequences of rows), consider that sequence to represent a vector and apply the previous algorithm on it. The computation ofS
is a bit more difficult in the matrix case, but it's not that hard to figure out. Let me know if you need more details.Update:
Here's how the algorithm would work on the following matrix, assuming
k = 12
:Consider the first row alone:
Consider it to be the vector
0 1 1 1 1 0
and apply the algorithm for the simpler problem on it: we find that there's no subsequence adding up to 12, so we move on.Consider the first two rows:
Consider them to be the vector
0+0 1+1 1+1 1+1 1+1 0+0 = 0 2 2 2 2 0
and apply the algorithm for the simpler problem on it: again, no subsequence that adds up to 12, so move on.Consider the first three rows:
Consider them to be the vector
0 3 3 3 3 0
and apply the algorithm for the simpler problem on it: we find the sequence starting at position 2 and ending at position 5 to be the solution. From this we can get the entire rectangle with simple bookkeeping.