我正在尝试编写一个解决maximum subarray problem的程序。我可以理解Kadane算法在1-D阵列上的直觉以及2-D阵列上的O(N ^ 4)实现。但是,我在理解二维阵列上的O(N ^ 3)实现时遇到了一些麻烦。
1)为什么我们将元素与同一列中前一行的元素相加?
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++)
array[i][j] += array[i-1][j];
}
2)我不了解算法的第二部分
试图在网上寻找解释,但无济于事。希望能在这里得到一些帮助!
提前致谢!
答案 0 :(得分:6)
您知道如何使用Kadane算法计算一维阵列上的最大和子数组。现在我们想要为2D数组扩展这个算法。对于O(N ^ 3)算法,我们有直觉。如果我们以某种方式创建N ^ 2子问题,然后尝试运行我们的O(N)Kadane算法,我们就可以解决最大子数组问题。
因此,基本上我们如何创建N ^ 2子问题是通过迭代矩阵的所有顶行和底行。然后我们尝试通过应用kadane的1D算法找到子阵列之间存在的最佳列。因此,我们将这两行之间的数字相加,然后在这个新形成的1D数组上应用kadane的1D算法。
但我们这里有一个问题。计算顶行和底行的所有O(n ^ 2)范围的和本身将是O(n ^ 4)。可以通过修改我们的矩阵来克服这个瓶颈,方法是将每个元素替换为该元素列中位于其上方的所有数字的总和。因此,现在我们可以通过减去矩阵中的相应数组来找出O(n)时间内任意两行之间的数字之和。
java伪代码 -
int kadane2D(int array[N+1][M+1]){
// Modify the array's elements to now hold the sum
// of all the numbers that are above that element in its column
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++){
array[i][j] += array[i-1][j];
}
}
int ans = 0; // Holds the maximum sum matrix found till now
for(int top=1; top<=N; top++){
for(int bottom=top; bottom<=N; bottom++){
// loop over all the N^2 sub problems
int[] sums = new int[N+1];
// store the sum of numbers between the two rows
// in the sums array
for(int i=0; i<=N; i++){
sums[i] = array[bottom][i] - array[top-1][i];
}
// O(n) time to run 1D kadane's on this sums array
ans = Math.max(ans, kadane1d(sums));
}
}
return ans;
}
答案 1 :(得分:2)
我知道这是一个老问题。但谷歌没有正确的答案,或者他们过度工作。
不,这不是正确的方法。工作示例,关于O(N ^ 2):
/**
* Kadane 1d
* @return max sum
*/
public static int maxSum(int[] a) {
int result = a[0]; //get first value for correct comparison
int sum = a[0];
for (int i = 1; i < a.length; i++) {
sum = Math.max(sum + a[i], a[i]); //first step getting max sum, temporary value
result = Math.max(result, sum);
}
return result;
}
/**
* Kadane 2d
* @param array
* @return max sum
*/
public static int maxSum2D(int array[][]){
int result = Integer.MIN_VALUE; //result max sum
for (int i = 0; i < array.length; i++) {
int sum = maxSum(array[i]);
result = Math.max(result, sum);
}
return result;
}
完整的例子:
答案 2 :(得分:1)
对于了解 Kadane的一维算法的人,以下内容应该很容易理解。基本上,我们尝试通过对每行使用prefix sum
将2D矩阵转换为1D。对于每个前缀和行,我们仅应用Kadane的1D算法。
只需发布有效的Python代码:
class Kadane2D:
def maxSumRetangle(self, grid):
def kadane1D(arr):
curmax, maxsofar = 0, float('-inf')
for a in arr:
curmax = max(a, curmax + a)
maxsofar = max(curmax, maxsofar)
return maxsofar
m, n, ans = len(grid), len(grid[0]), float('-inf')
colCum = [[0] * n]
for row in grid:
colCum.append([pre + now for pre, now in zip(colCum[-1], row)])
for top in range(1, m + 1):
for bottom in range(top, m + 1):
sums = [b - t for b, t in zip(colCum[bottom], colCum[top - 1])]
ans = max(ans, kadane1D(sums))
return ans
grid = [[1, 2, - 3], [3, 4, -6]]
assert Kadane2D().maxSumRetangle(grid) == 10
grid = [[1, 2, -1, -4, -20],
[-8, -3, 4, 2, 1],
[3, 8, 10, 1, 3],
[-4, -1, 1, 7, -6]]
assert Kadane2D().maxSumRetangle(grid) == 29