第一题:Leetcode376. 摆动序列
题目描述
解题思路
使用两个变量:preDiff 和 curDiff,分别记录 前一次相邻元素差值和 此处相邻元素值之差,只有当preDiff 和 curDiff 符号不同,摆动序列长度加一。
初始:长度为1。
题解1——贪心:移除坡上的元素。
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int ans = 1;
int curDiff = 0, preDiff = 0;
for (int i = 0; i < nums.size() - 1; i++) {
curDiff = nums[i + 1] - nums[i];
if ((preDiff >= 0 && curDiff < 0) ||
(preDiff <= 0 && curDiff > 0)) {
ans++;
preDiff = curDiff;
}
}
return ans;
}
};
题解2——动态规划
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
// dp[i][0]表示考虑下标为i的元素以及之前的元素,i作为山峰的最长长度
// dp[i][1]表示考虑下标为i的元素以及之前的元素,i作为山谷的最长长度
vector<vector<int>> dp(nums.size() + 1, vector<int>(2, 0));
dp[0][0] = dp[0][1] = 1;
for (int i = 1; i < nums.size(); i++) {
dp[i][0] = dp[i][1] = 1;
for (int j = 0; j < i; j++) {
// i作为山峰
if (nums[i] > nums[j])
dp[i][0] = max(dp[i][0], dp[j][1] + 1);
// i作为山谷
if (nums[i] < nums[j])
dp[i][1] = max(dp[i][1], dp[j][0] + 1);
}
}
return max(dp[nums.size() - 1][0], dp[nums.size() - 1][1]);
}
};
要点
- dp数组的意义:dp[i][0]表示考虑下标为i的元素以及之前的元素、i作为山峰的最长长度; dp[i] [1]表示考虑下标为i的元素以及之前的元素、i作为山谷的最长长度。
- 初始化:dp[i][0]和dp[i][1]均初始化为1(表示
这个元素本身就可以作为波峰或者波谷)。class Solution { public: int maxSubArray(vector<int>& nums) { int ans = INT_MIN; int count = 0; for (int i = 0; i < nums.size(); i++) { count += nums[i]; if (count > ans) { ans = count; } if (count < 0) count = 0; } return ans; } };
- 递推方法:对于所有j大于0、小于i,依次比较计算dp[i][0]和dp[i][1]
第二题:Letcode53. 最大子数组和
题目描述
题解1
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int ans = INT_MIN;
int count = 0;
for (int i = 0; i < nums.size(); i++) {
count += nums[i];
if (count > ans) {
ans = count;
}
if (count < 0)
count = 0;
}
return ans;
}
};
如果 count < 0,则后续计算不加上 nums[i]。
题解2——动态规划
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> dp(nums.size()); // dp[i]表示 以0 <= j <= i开始、以 i 结尾
// 的最大子数组和
dp[0] = nums[0];
int ans = dp[0];
for (int i = 1; i < nums.size(); i++) {
dp[i] = max(dp[i - 1] + nums[i], nums[i]);
if (dp[i] > ans) {
ans = dp[i];
}
}
return ans;
}
};