这个问题是二维最大子矩阵和问题,是一维最大子数组和问题的扩展。我们可以使用动态规划和 Kadane 算法的思想来解决这个问题。以下是 C++ 实现:
class Solution {
public:
vector<int> maxSubMatrix(vector<vector<int>>& matrix) {
// 检查矩阵是否为空
if (matrix.empty() || matrix[0].empty()) return {};
int rows = matrix.size(), cols = matrix[0].size();
int maxSum = INT_MIN;
// 结果向量:左边界,上边界,右边界,下边界,最大和
vector<int> result(5, 0);
// 遍历所有可能的左边界
for (int left = 0; left < cols; left++) {
// temp数组用于存储当前左右边界之间的列和
vector<int> temp(rows, 0);
// 遍历所有可能的右边界
for (int right = left; right < cols; right++) {
// 更新temp数组,加上当前列
for (int i = 0; i < rows; i++) {
temp[i] += matrix[i][right];
}
// 在temp数组上应用Kadane算法
int kadaneSum = 0, kadaneStart = 0, kadaneEnd = -1;
int currentSum = 0, tempStart = 0;
// Kadane算法:在temp数组中寻找最大子数组和
for (int i = 0; i < rows; i++) {
currentSum += temp[i];
if (currentSum < 0) {
// 如果当前和为负,重新开始
currentSum = 0;
tempStart = i + 1;
} else if (currentSum > kadaneSum) {
// 更新Kadane的最大和及其边界
kadaneSum = currentSum;
kadaneStart = tempStart;
kadaneEnd = i;
}
}
// 如果找到更大的和,更新全局结果
if (kadaneSum > maxSum) {
maxSum = kadaneSum;
result = {left, kadaneStart, right, kadaneEnd, maxSum};
}
}
}
return result;
}
};
这个算法的工作原理如下:
- 我们使用两个嵌套的循环来尝试矩阵的所有可能的左边界和右边界。
- 对于每一对左右边界,我们计算这些列的和,存储在
temp
数组中。 - 然后,我们在
temp
数组上应用 Kadane 算法来找到最大的子数组和,这对应于给定左右边界下的最大子矩阵。 - 我们保持跟踪全局最大和及其对应的左、上、右、下边界。
- 最后,我们返回一个包含最大和子矩阵的左、上、右、下边界和最大和的向量。
这个算法的时间复杂度是 O(n^3),其中 n 是矩阵的行数和列数中的较大者。虽然这不是最优的解法(存在 O(n^3) 的解法),但它相对容易理解和实现。
空间复杂度是 O(n),因为我们使用了一个额外的数组来存储列的和。
这个算法可以处理包含正数、负数和零的整数矩阵。它也可以处理全负数的情况,在这种情况下,它会返回矩阵中最大的单个元素。