二维最大子数组
Bentley 的Programming Pearls(第二版)在有关最大子数组问题的章节中描述了其二维版本:
...我们有一个 n × n 实数数组,我们必须找到任何矩形子数组中包含的最大和。这个问题的复杂性是多少?
Bentley 提到,截至该书出版之日(2000 年),寻找最佳解决方案的问题尚未解决。
现在还是这样吗?哪个是最著名的解决方案?有最近的文献吗?
Bentley's Programming Pearls (2nd ed.), in the chapter about the maximum subarray problem, describes its two-dimensional version:
...we are given an n × n array of reals, and we must find the maximum sum contained in any rectangular subarray. What is the complexity of this problem?
Bentley mentions that, as of the book's publication date (2000), the problem of finding an optimal solution was open.
Is it still so? Which is the best known solution? Any pointer to recent literature?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这个问题(最大子数组)的一维解决方案是 Theta(n),使用一种名为“Kadane 算法”的算法(我确信还有其他算法,但我对此有个人经验)。使用 Kadane 算法的实现,该问题的 2D 解决方案(最大子矩形)已知为 O(n^3)(我再次确定还有其他算法,但我以前使用过这个算法)。
虽然我们知道 Theta(n^3) 可以找到二维解,但没有人能够证明 n^3 是否是下界。对于许多算法来说,当增加维度时,算法的下限就会增加一个常数值。对于这个特定的问题,复杂性不会线性增加,因此没有已知的解决方案适用于任何给定的维度,因此问题仍然悬而未决。
参考类似的情况:我们知道2个矩阵可以在n^3次内相乘。我相信还有一种算法可以在 n^2.8 中做到这一点。然而,没有数学表明我们不能让它低于 n^2.8,所以它仍然是一个“开放”算法。
The 1D solution to this problem (the maximal sub-array) is Theta(n) using an algorithm called "Kadane's Algorithm" (there are other algorithms I'm sure, but I have personal experience with this one). The 2D solution to this problem (the maximal sub-rectangle) is known to be O(n^3) using an implementation of Kadane's Algorithm (again I'm sure there's others, but I've used this before).
Although we know that the 2D solution can be found in Theta(n^3), no one has been able to prove whether or not n^3 is the lower bound. For many algorithms, when you increase a dimension you increase the lower bound on the algorithm by a constant magnitude. With this particular problem the complexity doesn't increase linearly, and therefore there is no known solution to work for any given dimension, thus the problem is still open.
In reference to a similar case: we know that 2 matrices can be multiplied together in n^3 time. There is also an algorithm out there that can do it in n^2.8 I believe. However, there is no math indicating that we can't get it lower than n^2.8, so it's still an "open" algorithm.
仅供参考,新版的书有一个答案,但它很模糊,我不知道它会带来什么。
无论如何,我会使用分而治之+动态规划来解决这个问题。我们将 MaxSum(x, y) 定义为以 NXN 数组左上角为界的矩形内任何子数组的最大总和,高度为 y,宽度为 x。 (因此问题的答案将在 MaxSum(n-1, n-1) 中)
MaxEnding(x, y-1) 是包含 Array[x, y-1] 中的 # 的任何子数组的最大和。
同样,MaxEnding(x-1, y) 是 Array[x-1, y] 中包含 # 的任何子数组的最大和。
MaxEndingXStart(x, y-1) 是子数组的起始 x 坐标,该子数组具有包含 Array[x, y-1] 中的 # 的任何子数组的最大总和。
MaxEndingYStart (x-1, y) 是具有 Array[x-1, y] 中包含 # 的任何子数组的最大总和的子数组的起始 y 坐标。
下面#4 和#5 中的 2 个总和可以通过在遍历每一列时保留特定行中遇到的所有元素的总和来轻松计算,然后减去 2 个总和以获得特定部分的总和。
要实现这一点,您需要采用自下而上的方法,因为您需要计算 Max(x, y-1)、Max(x-1, y)、MaxEnding(x, y-1) 和 MaxEnding( x-1, y).. 因此您可以在计算 MaxEnding(x, y) 时进行查找。
FYI, the new edition of the book has an answer, but it is so vague, I don't know what it would entail.
In any case, I would use divide and conquer + dynamic programming to solve this. Let's define MaxSum(x, y) as the maximum sum of any subarray inside the rectangle bounded by the top-left most corner of the N X N array, with height y and width x. (so the answer to the question would be in MaxSum(n-1, n-1))
MaxEnding(x, y-1) is the maximum sum of any subarray that INCLUDES the # in Array[x, y-1].
Likewise, MaxEnding(x-1, y) is the maximum sum of any subarray that INCLUDES the # in Array[x-1, y].
MaxEndingXStart(x, y-1) is the STARTING x coordinate of the subarray that has the maximum sum of any subarray that INCLUDEs the # in Array[x, y-1].
MaxEndingYStart (x-1, y) is the STARTING y coordinate of the subarray that has the maximum sum of any subarray that INCLUDES the # in Array[x-1, y].
The 2 sum's in #4 and #5 below can be computed easily by keeping the sum of all elements encountered in a specific row, as you go through each column, then subtracting 2 sums to get the sum for a specific section.
To implement this, you would need to do a bottom-up approach, since you need to compute Max(x, y-1), Max(x-1, y), MaxEnding(x, y-1), and MaxEnding(x-1, y).. so you can do lookups when you compute MaxEnding(x, y).