leetcode 376. Wiggle Subsequence 最长摆动序列 + 动态规划DP + 这道题很棒
A sequence of numbers is called a wiggle sequence if the differences between successive numbers strictly alternate between positive and negative. The first difference (if one exists) may be either positive or negative. A sequence with fewer than two elements is trivially a wiggle sequence.
For example, [1,7,4,9,2,5] is a wiggle sequence because the differences (6,-3,5,-7,3) are alternately positive and negative. In contrast, [1,4,7,2,5] and [1,7,4,5,5] are not wiggle sequences, the first because its first two differences are positive and the second because its last difference is zero.
Given a sequence of integers, return the length of the longest subsequence that is a wiggle sequence. A subsequence is obtained by deleting some number of elements (eventually, also zero) from the original sequence, leaving the remaining elements in their original order.
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
想了好久没想到怎么做,网上看到了一个DP的做法,真的很妙。
使用用up[i]和down[i]分别记录到第i个元素为止以上升沿和下降沿结束的最长“摆动”序列长度,遍历数组,如果nums[i]>nums[i-1],表明第i-1到第i个元素是上升的,因此up[i]只需在down[i-1]的基础上加1即可,而down[i]保持down[i-1]不变;如果nums[i]
/*
* 用up[i]和down[i]分别记录到第i个元素为止以上升沿和下降沿结束的最长“摆动”
* 序列长度,遍历数组,如果nums[i]>nums[i-1],表明第i-1到第i个元素是上升的,
* 因此up[i]只需在down[i-1]的基础上加1即可,而down[i]保持down[i-1]不变;
* 如果nums[i]<nums[i-1],表明第i-1到第i个元素是下降的,因此down[i]
* 只需在up[i-1]的基础上加1即可,而up[i]保持up[i-1]不变;如果nums[i]==nums[i-1],
* 则up[i]保持up[i-1],down[i]保持down[i-1]。比较最终以上升沿和下降沿结束的
* 最长“摆动”序列长度即可获取最终结果
* */
class Solution
{
public int wiggleMaxLength(int[] nums)
{
if(nums==null || nums.length<=0)
return 0;
int[] up=new int[nums.length];
int[] down=new int[nums.length];
up[0]=down[0]=1;
for(int i=1;i<nums.length;i++)
{
if(nums[i]>nums[i-1])
{
up[i]=down[i-1]+1;
down[i]=down[i-1];
}else if(nums[i]<nums[i-1])
{
up[i]=up[i-1];
down[i]=up[i-1]+1;
}else
{
up[i]=up[i-1];
down[i]=down[i-1];
}
}
return Math.max(up[nums.length-1], down[nums.length-1]);
}
}
下面是C++的做法
很明显这就是一个动态规划DP问题,但是没想清楚怎么做,看了一下答案,就是这么做,这道题太棒啦,很值得学习和反思
代码如下:
#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <string>
#include <climits>
#include <algorithm>
#include <sstream>
#include <functional>
#include <bitset>
#include <numeric>
#include <cmath>
#include <regex>
using namespace std;
class Solution
{
public:
int wiggleMaxLength(vector<int>& nums)
{
if (nums.size() <= 1)
return nums.size();
vector<int> up(nums.size(), 0);
vector<int> down(nums.size(), 0);
up[0] = down[0] = 1;
for (int i = 1; i < nums.size(); i++)
{
if (nums[i] > nums[i - 1])
{
up[i] = down[i - 1] + 1;
down[i] = down[i - 1];
}else if (nums[i] < nums[i - 1])
{
up[i] = up[i-1];
down[i] = up[i - 1] + 1;
}
else
{
up[i] = up[i - 1];
down[i] = down[i - 1];
}
}
return max(up.back(), down.back());
}
};
还没有评论,来说两句吧...