线性解法:
定义up[i]表示从0到i组成最长的wiggle序列,并且序列的最后两个元素a,b的差是正的,即a<b;
同理down[i]表示从0到i组成的最长wiggle序列,并且序列最后的两个元素a和b的差是负的,即a>b;
状态转移方程:
up[i] = down[i-1]+1 (nums[i]>nums[i-1])
up[i-1] (nums[i] <= nums[i-1])
down[i] = up[i-1]+1 (nums[i]<nums[i-1])
down[i-1] (nums[i] >= nums[i-1])
分析如下:
当nums[i]>nums[i-1]:
Sdown[i-1]表示0到i-1组成的最长wiggle序列,最后一组差值为负,设最后一个元素为N
如果Sdown[i-1]包含nums[i-1], 那么自然up[i] = down[i-1]+1;
如果Sdown[i-1]不包含nums[i-1]:
1. N<nums[i-1], 由nums[i-1]<nums[i],得N<nums[i],也是成立的;
2. 如果N>nums[i-1],那么用nums[i-1]替换N,得到新的Sdown[i-1]序列,依然是最后一个递减的,长度也是最长的,也是成立的;
对于nums[i]==nums[i-1],得到的结果和nums[i-1]得到的结果是一样的;
对于nums[i] < nums[i-1]:
假设存在Sdown[i-1]的序列可以加上nums[i]得到更长的序列,设Sdown[i-1]最后一个元素是N,则N<nums[i];
因为nums[i]<nums[i-1], 所以N<nums[i-1],这意味着,如果存在使用nums[i-1]得到更长的序列,这个序列在计算up[i-1]的时候已经更新到了,所以up[i] = up[i-1];
down[i]原理以此类似,这里不展开了。
时间负载度O(n),注意到这里计算up[i]和down[i],只需要用到up[i-1]和down[i-1],所以空间复杂度可以优化到O(1)。
代码如下:
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n = nums.size();
if(n==0) return 0;
int up = 1, down = 1;
for(int i = 1; i<nums.size(); i++){
if(nums[i]>nums[i-1]){
up = down+1;
} else if(nums[i]<nums[i-1]){
down = up+1;
}
}
return max(up, down);
}
};
本文介绍了最长摆动序列的线性解法,定义了up[i]和down[i]分别表示从0到i组成的最长摆动序列,且最后两个元素差为正和负的情况。给出状态转移方程,并对不同情况进行分析,时间复杂度为O(n),空间复杂度可优化到O(1)。
895

被折叠的 条评论
为什么被折叠?



