子数组系列一(数组中连续的一段)
点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃
1.最大子数组和
题目链接: 53. 最大子数组和
题目分析:
子数组 是数组中的一个连续部分。子数组最少包含一个元素也就是说本身也是子数组!
算法原理:
1.状态表示
像这种研究的是子数组这样的模型,状态表示 依旧可以用 经验 + 题目要求
以 i 位置为结尾,巴拉巴拉。
以 i 位置为结尾,我们要的是最大子数组和,是不是先把以 i 位置为结尾的所有子数组拿到。单独 i 元素 是一个子数组,还有前面以 i 元素 为结尾的所有子数组,我要的是一个最大和。
dp[i] 表示:以 i 位置元素为结尾的所有子数组中的最大和。
2.状态转移方程
找出所有子数组最大和就可以了,所有子数组可以划分两大类。第一类就是单独自己构成子数组,第二类就是它自己与前面元素的结合构成子数组。所以可以根据长度来划分,长度为1 单独自己构成子数组,子数组最大和 nums[i],长度大于1,nums[i]一定是要的,然后在找到以 i - 1 位置元素为结尾的所有子数组中的最大和,两个相加就可以了,而dp[i - 1] 就是以 i - 1 位置元素为结尾的所有子数组中的最大和,因此 dp[i + 1] + nums[i],我要求的是 i 位置元素为结尾的所有子数组中的最大和。因此两种情况取最大就好了
3.初始化
多申请一个节点
- 里面的值要保证后面填表的正确
- 下标映射关系
先考虑如果不多加一个节点第一个位置应该填多少呢?是不是填自己本身啊,为了不让多加的节点影响后面的填表正确,因此可以给 0。注意下标映射关系,我们躲开了一个空间相当于整体往右移动一位,如果要回原数组下标要 -1
4.填表顺序
从左往右
5.返回值
注意这里可不是返回最后一个位置的值,因为最大子数组可能在这个数组中任何一个地方。所以返回的是dp中最大值
class Solution {
public:
int maxSubArray(vector<int>& nums) {
// 1.创建 dp 表
// 2.初始化
// 3.填表
// 4.返回值
int n = nums.size();
vector<int> dp(n + 1);
for(int i = 1; i <= n; ++i)
{
dp[i] = max(nums[i - 1], dp[i - 1] + nums[i - 1]);
}
int ret = INT_MIN;
for(int i = 1; i <= n; ++i)
ret = max(ret,dp[i]);
return ret;
}
};
2.环形子数组的最大和
题目链接: