子数组或者子矩阵的最大累加和问题
子数组或者子矩阵的最大累加和问题
作者: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();
}
}
更多
本文来自博客园,作者:Grey Zeng,转载请注明原文链接:https://www.cnblogs.com/greyzeng/p/16326526.html