题目描述:
给定一个整数矩阵,请找出一个子矩阵,使得其数字之和等于0.输出答案时,请返回左上数字和右下数字的坐标。
样例:
给定矩阵
[
[1 ,5 ,7],
[3 ,7 ,-8],
[4 ,-8 ,9],
]
返回 [(1,1), (2,2)]
思路讲解:
首先我们看一下题,发现是和为0的子矩阵,返回的是左上点和右下点,这样我们就可以直接利用四层循环,来循环找出不同的左上点和右下点,然后看其是否为0,如果为0,就将这两个点的坐标返回,但是如何求其之间的和呢?第一种就是暴力求解,直接循环求和,这样的方法简单,但是最后的时间估计会超时,仔细分析一下超时的原因,就是由于我们每一次重复计算了很多次的加法,例如计算matrix[x1][y1]–matrix[x2][y2],下一次计算matrix[x1+1][y1+1]–matrix[x2][y2],有重复计算了他们之间的一些加法,所以,我考虑将这些重复计算的提前算出来,这个时候我就考虑提前计算出每一个点到位置00的和,这样我们在计算某个子矩阵的时候,就可以使用其进行加减得到想要区域子矩阵的和。
举个栗子:
例如:
[
[1 ,5 ,7],
[3 ,7 ,-8],
[4 ,-8 ,9],
]
其的和矩阵sum为
[
[1 ,6 ,13],
[4 ,16 ,15],
[8 ,12 ,20],
]
比如我们求(1,1)到(2,2)子矩阵的和,我们只需要将sum[2][2]-sum[0][2]-sum[2][0]+sum[0][0]这样我们就得到了我们想要的和。
上图中假如每一个区域都是该点到(0,0)的子矩阵和,所以我们要求(i,j)这个区域的和,我们就可以通过sum[i][j]-sum[i-1][j]-sum[i][j-1]+sum[i-1][j-1]得到我们想要的子矩阵和。
这里还有一个需要解释的点就是关于如何求和矩阵的方法,我们通过上面类似的方法,就是sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+matrix[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) {
// write your code here
int m=matrix.size();
int n=matrix[0].size();
cout<<m<<" "<<n<<endl;
int **map=new int*[m];
for(int i=0;i<m;i++){
map[i]=new int[n];
}
map[0][0] = matrix[0][0];//生成和矩阵
for(int i =1;i<m ;i++)
map[i][0] =map[i-1][0] + matrix[i][0];
for(int j =1;j<n ;j++)
map[0][j] =map[0][j-1] + matrix[0][j];
for(int i =1;i<m;i++){
for(int j=1;j<n;j++){
map[i][j] = map[i-1][j] + map[i][j-1] - map[i-1][j-1] + matrix[i][j];
}
}
vector<vector<int>>res(2);
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
for(int x=i;x<m;x++){
for(int y=j;y<n;y++){
if(judge_is_zero(map,i,j,x,y)==0){
res[0].push_back(i);
res[0].push_back(j);
res[1].push_back(x);
res[1].push_back(y);
return res;
}
}
}
}
}
}
int judge_is_zero(int **map,int x1,int y1,int x2,int y2){//通过和矩阵计算子矩阵的和
int a=0,b=0,c=0,d=0;
int a1=x1-1,a2=y1-1;
int b1=x1-1,b2=y2;
int c1=x2,c2=y1-1;
int d1=x2,d2=y2;
if(a1<0||a2<0){
a=0;
}else{
a=map[a1][a2];
}
if(b1<0||b2<0){
b=0;
}else{
b=map[b1][b2];
}
if(c1<0||c2<0){
c=0;
}else{
c=map[c1][c2];
}if(d1<0||d2<0){
d=0;
}else{
d=map[d1][d2];
}
return a+d-b-c;
}
};