1. 程式人生 > 其它 >子陣列或者子矩陣的最大累加和問題

子陣列或者子矩陣的最大累加和問題

作者:Grey

原文地址:子陣列或者子矩陣的最大累加和問題

子陣列的最大累加和

題目連結:LeetCode 53. 最大子陣列的和

主要思路:

設定dp陣列,長度和原始陣列一樣,dp[i]表示必須以i位置結尾的子陣列,最大累加和是多少,設定一個全域性max,獲取dp陣列的最大值,即為原始陣列的最大子陣列的和。

顯然有:

// 必須以0位置結尾的子陣列,最大累加和顯然就是arr[0]
dp[0] = arr[0]

考慮普遍位置

// dp[i-1]表示:必須以i-1位置的數結尾的最大子陣列累加和是多少
// dp[i]表示:必須以i位置的數結尾的最大子陣列累加和是多少
// 假設dp[i-1]>0,則dp[i-1]的和可以給予dp[i]幫助
// 否則,dp[i-1]不能給予dp[i]幫助,此時,dp[i] = arr[i]
dp[i] = arr[i] + (dp[i-1]>0?dp[i-1]:0);

完整程式碼如下

 public static int maxSubArray(int[] arr) {
		// dp[i]表示:子陣列必須以i結尾的情況下,最大累加和是多少
		int[] dp = new int[arr.length];
		int max = arr[0];
		dp[0] = arr[0];
		for (int i = 1; i < arr.length;i++) {
			dp[i] = arr[i] + (Math.max(dp[i - 1], 0)); 
			max = Math.max(max,dp[i]);
		}
		return max;
 }

通過如上演算法,可以看到dp[i]

只依賴dp[i-1]位置的值,所以,dp陣列可以簡化成兩個變數,依次傳遞下去,優化後的完整程式碼如下:

	public static int maxSubArray(int[] arr) {
		int pre = arr[0];
		int max = pre;
		for (int i = 1; i < arr.length; i++) {
			int cur = arr[i] + (Math.max(pre, 0));
			max = Math.max(max, cur);
			pre = cur;
		}
		return max;
	}

子矩陣的最大累加和問題

題目連結:子矩陣的最大累加和問題

這個題目可以借鑑子陣列的最大累加和問題的演算法,假設我們的二位矩陣是:

[a,b,c,d,e]
[f,g,h,i,j]
[k,l,m,n,o]
[p,q,r,s,t]
[u,v,w,x,y]

假設客觀上,最大子矩陣的和是這些數的和

[k,l,m]
[p,q,r]
[u,v,w]

即第3行,第4行,第5行的前面三個陣列成的矩陣,其實,它就是,第3行到第5行的對應位置數字之和組成的一維陣列的最大子陣列的累加和

[k+p+u,l+q+v,m+r+w,n+s+x,o+t+y]

這樣一來,我們可以把問題轉換一下,必須以i行為底的子矩陣的最大累加和是多少,如果我們求得了每一行的這個指標,那麼最大值就是本題的答案。比如:必須以第2行為底的子矩陣的最大累加和,我們可以這樣算:

第0行~第2行的對應位置資料累加後的一維陣列

[a+f+k,b+g+l,c+h+m,d+i+n,e+j+o]

子陣列最大累加和為max1,

第1行~第2行的對應位置資料累加和後的一維陣列

[f+k,g+l,h+m,i+n,j+o]

子陣列最大累加和為max2,

第2行單獨一行的一維陣列是

[k,l,m,n,o]

子陣列最大累加和為max3

那麼必須以第2行為底的子矩陣的最大累加和就是max1,max2,max3中的最大值。

對每一行都求這個指標,得到每一行為底的最大子矩陣累加和,得到全域性最大的那個就是答案。

完整程式碼如下:

import java.util.Scanner;

public class Main {
    public static int maxSum(int[][] matrix, int n, int m) {
        int[] t;
        int max = maxSubArray(matrix[0]);
        for (int i = 0; i < n; i++) {
            max = Math.max(maxSubArray(matrix[i]), max);
            t = matrix[i];
            for (int k = i + 1; k < n; k++) {
                for (int j = 0; j < m; j++) {
                    t[j] += matrix[k][j];
                }
                max = Math.max(max, maxSubArray(t));
            }
        }
        return max;
    }

    public static int maxSubArray(int[] arr) {
        int pre = arr[0];
        int max = pre;
        for (int i = 1; i < arr.length; i++) {
            int cur = arr[i] + (Math.max(pre, 0));
            max = Math.max(max, cur);
            pre = cur;
        }
        return max;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int[][] matrix = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                matrix[i][j] = in.nextInt();
            }
        }
        System.out.println(maxSum(matrix, n, m));
        in.close();
    }
}

更多

演算法和資料結構筆記