leeched-day5
动态规划
- 53最大子数组和
题目描述:
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。
53.最大子数组和
思路:
首先需要把题意理解清楚,要找到一个具有最大和的连续子数组。比较重要的是最大和,连续子数组。
我们可以将每一个子问题dp[i]
定义为以nums[i]
结尾的具有最大和的连续子数组,然后对于每一个子问题,我们的状态转移方程可以定义为dp[i] = max{dp[i]+nums[i],dp[i]}
;如果nums[i]>0
,那么dp[i]=dp[i]+nums[i]
,否则dp[i]=nums[i]
,也就是说,dp[i] = max{dp[i]+nums[i],dp[i]}
。
关键代码:
for (int i = 1; i < nums.length; i++) {
dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
maxValue = Math.max(maxValue,dp[i]);
}
简化代码,我们可以用一个变量来代替dp[i]
,即代码可以变成
int pre = 0;//当前最大连续子数组和
int res = nums[0];//最大连续子数组和
for (int num : nums) {
pre = Math.max(pre + num, num);
res = Math.max(res, pre);
}
- 918.环形子数组的最大和
题目描述:
给定一个长度为 n 的环形整数数组 nums ,返回 nums 的非空 子数组 的最大可能和 。
环形数组 意味着数组的末端将会与开头相连呈环状。形式上, nums[i] 的下一个元素是 nums[(i + 1) % n] , nums[i] 的前一个元素是 nums[(i - 1 + n) % n] 。
子数组 最多只能包含固定缓冲区 nums 中的每个元素一次。形式上,对于子数组 nums[i], nums[i + 1], ..., nums[j] ,不存在 i <= k1, k2 <= j 其中 k1 % n == k2 % n 。
918.环形子数组的最大和
思路:
这道题跟53最大子数组和类似,区别就是这道题的最大和数组可能是环形的,而上一题是线性的。所以相当于这道题是在上一题的基础上添加了一种可能性。
看了国外的那个题解,感觉思路就顿时开阔了,真的厉害。
我们要求最大连续子数组和,加一个环形数组的条件就有两种情况,分别是:
1. 跟53一样,最大连续子数组出现在数组的中间部分。
2.最大连续子数组出现在数组的首尾,从而构成一个环形
如果是第二种情况的话,因为数组的总和是一样的,那么我们可以知道,如果首尾连接所得到的值最大的话,那么中间部分所得到的值就是最小的。
所以对于第一种情况,我们可以使用53的方法,记录连续子数组的最大和,对于第二种情况,记录连续子数组的最小和,如果是最小和,那么就需要用数组的和减去最小和,即的连续子数组的最大和。
关键代码:
for(int i = 1;i<nums.length;i++){
currentMax = Math.max(currentMax+nums[i],nums[i]);
maxValue = Math.max(currentMax,maxValue);
currentMin = Math.min(currentMin+nums[i],nums[i]);
minValue = Math.min(currentMin,minValue);
total += nums[i];
}
到这里我们就求到了整个连续子数组的最大和和最小和,那么我们怎么知道此时的数组是第一种还是第二种情况呢?
我们可以知道,如果说是第二种情况,那么我们的最大和就是total-minValue
,于是我们就可以将total-minValue
和maxValue
比较,取较大的那个值。
但是此时有一种特殊情况,如果说最大连续子数组的和是负数,那么此时数组的值一定全是负数,于是计算所得的最小值等于整个数组和,minValue=total
,此时total-minValue=0
,此时这种情况是有问题的。所以说如果最大和是负数,那么我们的连续子数组最大和就是maxValue
,否则才是max(maxValue,total-minValue)
,即方法返回 return maxValue>0?Math.max(maxValue,total-minValue):maxValue;
。
这种思路最妙的一点就在于整个数组值是固定的,如果某个连续子数组和最大,那么剩余的环形子数组和就该最小;反之亦然。
但是有一种特殊情况是数组的值全是负数或者正数的情况,如果数组值全是正数,那么连续子数组最小和以及连续子数组最大和还有总和都相等;如果数组全是负数,那么连续子数组最小和以及数组总和相等。我们要规避这些情况发生所以最后还需要处理一下返回值。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 我与微信审核的“相爱相杀”看个人小程序副业
· DeepSeek “源神”启动!「GitHub 热点速览」
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库