1. 程式人生 > >lintcode---和為零的子矩陣

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; } };