最大子序和
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [5,4,-1,7,8]
输出:23
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
解法一:动态规划+贪心思想
首先要明白以下几点:
- 设置dp[i]为第i位的暂存值(注意:不是最大值,只是下标滑到第i位时,dp的数值)
- 最大子序和的第一位一定为 正数,
- 如果一个序列全为负数,那么就要求负数的最大值(不要想当然的觉得最大数大于0!然后就随随便便的把dp[i]=0),
- 如果
dp[i-1]<=0
,那么就要勇敢舍弃前面算的,从当前位重新开始(违反第2条)。 - 如果
dp[i-1]>0
,当然要加上当前位(贪心),至于加上当前位后是会减少dp[i]或者增加,留给下一个循环去判断。
代码如下:
class Solution {
public int maxSubArray(int[] nums) {
int [] dp = new int [nums.length];
dp[0] = nums[0];
for(int i=1;i<nums.length;i++){
if(dp[i-1]<=0){
dp[i] = nums[i];
}
else{
dp[i] = dp[i-1]+nums[i];
}
}
java.util.Arrays.sort(dp);
return dp[nums.length-1];
}
}
上述代码并没有清楚的写出动态规划的统一方程,但由for循环中的两个if,
if(dp[i-1]<=0){
dp[i] = nums[i];
}
else{
dp[i] = dp[i-1]+nums[i];
}
可以推测dp公式:dp[i] = nums[i]+Math.max(dp[i-1], 0)
故上述代码可简化为:
class Solution {
public int maxSubArray(int[] nums) {
int [] dp = new int [nums.length];
dp[0] = nums[0];
int max = dp[0];
for(int i=1;i<nums.length;i++){
dp[i] = nums[i] + Math.max(dp[i-1], 0);
max = Math.max(dp[i], max);
}
return max;
}
}
继续优化
class Solution {
public int maxSubArray(int[] nums) {
int temp_i = nums[0];
int max = nums[0];
for(int i=1;i<nums.length;i++){
temp_i = nums[i] + Math.max(temp_i, 0);
max = Math.max(temp_i, max);
}
return max;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix