题目
给出一个整数序列,求摆动子序列,即子序列相邻两位之间的差值是正负交替出现的,即序列中相邻两个数一大一小交替出现。
Examples:
Input: [1,7,4,9,2,5]
Output: 6
The entire sequence is a wiggle sequence.
Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].
Input: [1,2,3,4,5,6,7,8,9]
Output: 2
思路
和之前动态规划做的Best Time to Buy and Sell Stock with Transaction Fee思路一模一样,这里再简单说一下好了。
满足题意的序列最后两个数的差值要么是正数,要么是负数,因此可以用两个数组记录两种信息,然后交替更新到数组最后一位即可。
定义状态
pos[i]: 从nums[0]到nums[i]范围内符合条件的最长子序列长度,而且最后一个差值是正数
neg[i]: 从nums[0]到nums[i]范围内符合条件的最长子序列长度,而且最后一个差值是负数
额外需要pos_end,neg_end记录两个序列的最后一位数字
最终结果为 max(pos[n - 1], neg[n - 1])
状态转移
可见每个状态都由之前的两个状态转移过来
更新pos[]
①当nums[i] - pos_end > 0时,nums[i]不能直接加到pos序列最后否则连续两个差值都是正值就违反规定了,但是由贪心策略,此时用nums[i]替换掉pos_end会使得以后寻找下一个数更有利,因为pos_end越大的话,下一个满足序列条件的数的范围也越大(下一个满足条件的数一定小于pos_end),因此 pos_end = nums[i] , pos[i] = pos[i - 1]
②当nums[i] - neg_end > 0时,pos_end = nums[i],pos[i] = neg[i - 1] + 1
则 pos[i] = max(pos[i - 1],neg[i - 1] + 1)
类似的更新neg[]
③当nums[i] - pos_end < 0时,neg_end = nums[i],neg[i] = pos[i - 1] + 1
④当nums[i] - neg_end < 0时,neg_end = nums[i],neg[i] = neg[i - 1]
则 neg[i] = max(neg[i - 1],pos[i - 1] + 1)
注意:当nums[i] - pos_end == 0时,pos序列的长度和最后一个数都不变,类似的当nums[i] - neg_end == 0时也一样,这里的赋值问题有点坑,直接看代码就清楚了
代码
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n = nums.size();
if (n <= 1) return n;
//pos[i]: 从nums[0]到nums[i]范围内符合条件的最长子序列长度,而且最后一个差值是正数
//neg[i]: 从nums[0]到nums[i]范围内符合条件的最长子序列长度,而且最后一个差值是负数
vector<int> pos(n);
vector<int> neg(n);
int pos_end = nums[0], neg_end = nums[0];
pos[0] = neg[0] = 1;
for (int i = 1; i < n; i++) {
// pos数组期待下一个差值是负值,neg期待下一个差值是正值
int expect_neg_diff = nums[i] - pos_end;
int expect_pos_diff = nums[i] - neg_end;
int lenx, leny;
// 更新pos[i],
// 给lenx和leny初始化长度为pos[i - 1],
// 既满足nums[i] - pos_end == 0时的情况,
// 也能避免当下面两个条件都不满足时出现lenx和leny为乱值。
lenx = leny = pos[i - 1];
if (expect_neg_diff > 0) {
pos_end = nums[i];
lenx = pos[i - 1];
}
if (expect_pos_diff > 0) {
pos_end = nums[i];
leny = neg[i - 1] + 1;
}
pos[i] = max(lenx, leny);
// 更新neg[i],初始化lenx和leny的理由同上
lenx = leny = neg[i - 1];
if (expect_pos_diff < 0) {
neg_end = nums[i];
lenx = neg[i - 1];
}
if (expect_neg_diff < 0) {
neg_end = nums[i];
leny = pos[i - 1] + 1;
}
neg[i] = max(lenx, leny);
}
return max(pos[n - 1], neg[n - 1]);
}
};