子陣列或者子矩陣的最大累加和問題
阿新 • • 發佈:2022-05-30
作者: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();
}
}