- Submatrix Sum
Given an integer matrix, find a submatrix where the sum of numbers is zero. Your code should return the coordinate of the left-up and right-down number.
If there are multiple answers, you can return any of them.
Example
Example 1:
Input:
[
[1, 5, 7],
[3, 7, -8],
[4, -8 ,9]
]
Output: [[1, 1], [2, 2]]
Example 2:
Input:
[
[0, 1],
[1, 0]
]
Output: [[0, 0], [0, 0]]
Challenge
O(n3) time.
解法1:
思路:基于LintCode138. Subarray Sum。遍历i行和j行的组合,将其中的行都累加起来,然后就可以用LintCode 138里面的解法来判断是不是有某段元素累加起来等于0了。
但我感觉这题调通并不容易。主要有两个地方要注意:
1)当输入是类似
[[-1,-1]
[-1,3]]
或
[[-1,-1,-1]
[-1,-1,-1]
[-1,-1,8]]
这样的matrix时,必须要考虑整个矩阵,这样,返回结果的左上方点一定在第0行。
2) 还要考虑在单独某行就会出现sum为0的情况,比如说本来就有0元素,或该行连续某段和为0(即LintCode 138情形)。所以我们要考虑i==j的情形,并且这种情形要单独处理。
代码如下:
class Solution {
public:
/*
* @param matrix: an integer matrix
* @return: the coordinate of the left-up and right-down number
*/
vector<vector<int>> submatrixSum(vector<vector<int>> &matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<vector<int>> rowSums(m, vector<int> (n, 0));
for (int i = 0; i < n; ++i) {
rowSums[0][i] = matrix[0][i];
}
for (int i = 1; i < m; ++i) {
for (int j = 0; j < n; ++j) {
rowSums[i][j] = rowSums[i - 1][j] + matrix[i][j];
}
}
vector<int> tempList(n, 0);
vector<vector<int>> result(2, vector<int>(2, 0));
for (int i = 0; i < m; ++i) {
for (int j = i; j < m; ++j) {
vector<int> tempResult = subArraySum(rowSums[j]);
if (tempResult.size() != 0) { //考虑整个矩阵
result[0][0] = 0;
result[0][1] = tempResult[0];
result[1][0] = j;
result[1][1] = tempResult[1];
return result;
}
for (int k = 0; k < n; ++k) {
if (j == i) {
tempList[k] = rowSums[j][k];
} else {
tempList[k] = rowSums[j][k] - rowSums[i][k];
}
}
tempResult = subArraySum(tempList);
if (tempResult.size() != 0) {
if (j == i)
result[0][0] = i;
else
result[0][0] = i + 1;
result[0][1] = tempResult[0];
result[1][0] = j;
result[1][1] = tempResult[1];
return result;
}
}
}
return vector<vector<int>>(2, vector<int>(2));
}
private:
vector<int> subArraySum(vector<int> &list) {
int n = list.size();
vector<int> result;
if (n == 0) return vector<int>();
long long sum = 0;
unordered_map<long long, int> preSums; //presum, index
for (int i = 0; i < n; ++i) {
sum += list[i];
if (sum == 0) return vector<int>{0, i};
if (preSums.find(sum) != preSums.end()) {
result.push_back(preSums[sum] + 1);
result.push_back(i);
break;
}
preSums[sum] = i;
}
return result;
}
};