lintcode---和為零的子矩陣
題目描述:
給定一個整數矩陣,請找出一個子矩陣,使得其數字之和等於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;
}
};