程序员面试金典——18.12最大和子矩阵

程序员面试金典——18.12最大和子矩阵

Solution1:
参考网址:
[1]https://www.cnblogs.com/GodA/p/5237061.html 思想讲的很清楚~
[2]https://www.nowcoder.com/profile/963612/codeBookDetail?submissionId=15224519
思路:
动态规划
  我们来分析一下最优子结构,若想找到n个数的最大子段和,那么要找到n-1个数的最大子段和,这就出来了。我们用b[i]来表示a[0]…a[i]的最大子段和,b[i]无非有两种情况:
  (1)最大子段一直连续到a[i]  
  (2)以a[i]为首的新的子段 。
  由此我们可以得到b[i]的状态转移方程: b[i]=max{b[i1]+a[i],a[i]} b [ i ] = m a x { b [ i − 1 ] + a [ i ] , a [ i ] } 。最终我们得到的最大子段和为 max{b[i],0<=i<n} m a x { b [ i ] , 0 <= i < n }
这跟最大子矩阵有什么关系呢?当然有关系学啦!二维就是一维的扩展,把二维压扁不就变成一维了吗?
  我们假设所求N*N的矩阵的最大子矩阵是从i列到j列,q行到p行,如下图所示(假设下标从1开始)
  a[1][1]  a[1][2]  ······  a[1][i]  ······  a[1][j]   ······  a[1][n]
  a[2][1]  a[2][2]  ······  a[2][i]  ······  a[2][j]   ······  a[2][n]
                  ······
  a[q][1]  a[q][2]  ······  a[q][i]  ······  a[q][j]  ······  a[q][n]
                  ······
  a[p][1]  a[p][2]  ······  a[p][i]  ······  a[p][j]  ······  a[p][n]
                  ······
  a[n][1]  a[n][2]  ······  a[n][i]  ······  a[n][j]  ······  a[n][n]
  最大子矩阵就是对角线为a[q][i]-a[p][j]的子矩阵,如果把最大子矩阵同列的加起来,我们可以得到一个一维数组 {a[q][i]++a[p][i],,a[q][j]++a[p][j]} { a [ q ] [ i ] + · · · · · · + a [ p ] [ i ] , · · · · · · , a [ q ] [ j ] + · · · · · · + a [ p ] [ j ] } ,现在我们可以看出,这其实就是一个一维数组的最大子段问题。如果把二维数组看成是纵向的一维数组和横向的一维数组,那问题不就迎刃而解了吗?把二维转换成了我们刚刚解决了的问题。

class SubMatrix {
public:
    int sumOfSubMatrix(vector<vector<int> > mat, int n) {
        // write code here
        if(n <= 0) 
            return 0;
        int maxVal = INT_MIN;
        for(int i = 0; i < n; i++) {
            vector<int> temp(mat[i]); //temp是一维行向量
            maxVal = max(maxVal, helper(temp));//先得到第i行的最大和
            for(int j = i + 1; j < n; j++) { //依次循环下面的n-i行,把每行里的n个数加到第i行中
                for(int k = 0; k < n; k++) { //i+1 =< j <= n-1,把第j行中n个数加到第i行中
                    temp[k] += mat[j][k];
                }
                maxVal = max(maxVal, helper(temp));//每当加完1行后就判断1次最大和
            }
        }
        return maxVal;
    }

    //求连续数组最大和,动态规划思想
    int helper(vector<int>& vec) { //求一维数组最大和
        int f = vec[0];
        int result = f;
        for(int i = 1; i < vec.size(); i++) {
            f = max(f+vec[i], vec[i]);
            result = max(result, f);
        }
        return result;
    }
};

PS:一道很不错的动态规划题,理解他着实费了点功夫

你可能感兴趣的:(程序员面试金典题目笔记)