算法——求矩陣中和最大的子矩陣


給定一個正整數、負整數和 0 組成的 N × M 矩陣,編寫代碼找出元素總和最大的子矩陣。

返回一個數組 [r1, c1, r2, c2],其中 r1, c1 分別代表子矩陣左上角的行號和列號,r2, c2 分別代表右下角的行號和列號。若有多個滿足條件的子矩陣,返回任意一個均可。
leetcode

解題思路:

  • 首先為了在O(1)的時間內獲取兩個點之間的矩陣和,就需要求每個點的前綴和,然后通過前綴和的是運算,快速獲取兩個點構成的矩陣的和。
  • 然后是遍歷整個數組,但是如果依次枚舉每兩個點的話,時間復雜度是n的四次方的,會超時。所以,這里需要利用動態規划的思想。如果讓一個維度不變,就可以把問題變為一維數組求和最小的連續字串問題,當前綴小於零,那就只會給后面添累贅,所以直接就去掉。
class Solution {
    public int[] getMaxMatrix(int[][] matrix) {
        int n = matrix.length;
        if(n == 0) return new int[0];
        int m = matrix[0].length;

        int[][] f = new int[n + 1][m + 1];
        int[][] s = new int[n + 1][m + 1];

		// 求二維的前綴和
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + matrix[i - 1][j - 1];
            }
        }

        int[] res = new int[4];
        int sum = matrix[0][0];

		// 先枚舉一個維度,再枚舉另一個維度,這樣就將為一維數組求和最大的連續子串問題。
        for(int i = 1; i < n + 1; i++) {
            for(int j = 0; j < i; j++) {
                int start = 0;
                for(int k = 1; k < m + 1; k ++) {
                    int cur = s[i][k] - s[j][k] - s[i][start] + s[j][start];
                    if(cur > sum) {
                        sum = cur;
                        res = new int[]{j, start, i - 1, k - 1};
                    }
					// 如果前面的和小於零,只會拖累后面,索性直接去掉前面的
                    if(cur < 0) start = k;
                }
            }
        }

        return res;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM