了解 2-D 数组的卡达内算法
Understanding Kadane's Algorithm for 2-D Array
我正在尝试编写一个解决最大子数组问题的程序。我可以理解 Kadane 算法在一维数组上的直觉,以及二维数组上的 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(我对算法的第二部分一无所知
尝试在网上寻找解释,但无济于事。希望在这里得到一些帮助!
提前感谢!
您知道如何使用 Kadane 算法计算一维数组上的最大总和子数组。现在我们想为 2D 数组扩展此算法。对于 O(N^3( 算法,我们有一种直觉。如果我们以某种方式创建 N^2 个子问题,然后尝试运行我们的 O(N( Kadane 算法,我们可以解决最大子数组问题。
所以基本上我们如何创建 N^2 子问题是通过迭代矩阵的所有顶部和底部行。然后,我们尝试通过应用 kadane 的一维算法找到子数组所在的最佳列。因此,我们将这两行之间的数字逐列求和,然后将 kadane 的一维算法应用于这个新形成的一维数组。
但是我们这里有一个问题。计算顶部和底部行的所有 O(n^2( 范围的总和本身将是 O(n^4(。这个瓶颈可以通过修改我们的矩阵来克服,方法是将每个元素替换为该元素列中高于它的所有数字的总和。因此,现在我们可以通过减去矩阵中的相应数组来找出 O(n( 时间内任意两行之间的数字总和。
java伪代码 -
int kadane2D(int array[N][M]){
// 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 = 0; j < M; j++){
array[i][j] += array[i-1][j];
}
}
int ans = 0; // Holds the maximum sum matrix found till now
for(int bottom = 0; bottom < N; bottom++){
for(int top = bottom; top < N; top++){
// loop over all the N^2 sub problems
int[] sums = new int[N];
// store the sum of numbers between the two rows
// in the sums array
for(int i = 0; i < M; i++){
if (bottom > 0) {
sums[i] = array[top][i] - array[bottom-1][i];
} else {
sums[i] = array[top][i];
}
}
// O(n) time to run 1D kadane's on this sums array
ans = Math.max(ans, kadane1d(sums));
}
}
return ans;
}
对于了解卡达内一维算法的人来说,下面应该很容易理解。基本上,我们尝试通过使用每行的prefix sum
将 2D 矩阵转换为 1D。对于每个前缀总和行,我们只应用 Kadane 的一维算法。
只需发布工作 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
这是一个老问题。但谷歌没有正确的答案,或者他们过度劳累。
不,这不是正确的方法。工作示例,在 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;
}
完整示例:
- 简单:https://pastebin.com/Qu1x0TL8
- 补充:https://pastebin.com/Tjv602Ad
- 带索引:https://pastebin.com/QsgPBfY6
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 求最大元素位置的分治算法
- 具有非整数边容量的最大流量的Dinic算法
- 到连接组件算法的问题(递归)
- STL算法函数在多个一维容器上的使用
- 读取最后一行代码算法 - c++ 时出现问题
- 括号更改 O(n) 算法
- std::unordered_map 搜索算法是如何实现的?
- 如何实现高效的算法来计算大型数据集的多个不同值?
- 如何在 Mac 上使用 c++17 并行标准库算法?