子数组或者子矩阵的最大累加和问题
子数组或者子矩阵的最大累加和问题
作者: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();
}
}
更多#
作者:GreyZeng
出处:https://www.cnblogs.com/greyzeng/p/16326526.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
你可以在这里自定义其他内容
本文来自博客园,作者:Grey Zeng,转载请注明原文链接:https://www.cnblogs.com/greyzeng/p/16326526.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战