题目描述
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。
例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。
示例1:
输入: [1,7,4,9,2,5]
输出: 6
解释: 整个序列均为摆动序列。
示例2:
输入: [1,17,5,10,13,15,10,5,16,8]
输出: 7
解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。
示例3:
输入: [1,2,3,4,5,6,7,8,9]
输出: 2
解题思路:使用贪心思想。
当数列部分区间为连续递增或者连续递减的时候,选取区间中最大的值,这样可以尽可能使下一个数字组成摆动序列
解法一:波峰和波谷之间差1。(leetcode大神的想法)
int wiggleMaxLength(vector<int>& nums) {//波峰和波谷相差为1
// [1,17,5,10,13,15,10,5,16,8]
if (nums.size() < 2) {
return nums.size();
}
int up = 1;//波峰起始为1
int down = 1;//波谷起始为1
for (int i = 1; i < nums.size(); i++) {
if (nums[i-1] < nums[i]) {
//上升序列
up = down + 1;
}
if (nums[i] < nums[i - 1]) {
//下降序列
down = up + 1;
}
}
return max(up,down);
}
解法二:使用标志位来判断是递增序列还是递减序列
int wiggleMaxLength(vector<int>& nums) {//使用标志位来判断
if (nums.size() < 2) {
return nums.size();
}
int max_length = 1;//序列的最大长度
int flag = 1;//标志位
bool start = true;//起始标志位,处理第一个数字
for (int i = 1; i < nums.size(); i++) {
if (nums[i - 1] < nums[i] && (flag == 1 || start)) {//上升序列
max_length++;
flag = -1;
start = false;
}
else if(nums[i] < nums[i-1] && (flag == -1 || start))//下降序列
{
max_length++;
flag = 1;
start = false;
}
}
return max_length;
}
解法三:使用状态机来实现,此种方法思路清晰,代码可读性强
int wiggleMaxLength2(vector<int>& nums) {//使用状态机实现
if (nums.size() < 2) {
return nums.size();
}
static const int BEGIN = 0;//开始状态
static const int UP = 1;//上升状态
static const int DOWN = 2;//下降状态
int STATE = BEGIN;
int max_length = 1;//序列长度最少为1
for (int i = 1; i < nums.size(); i++) {
switch (STATE)
{
case BEGIN:
if (nums[i - 1] < nums[i]) {
STATE = UP;
max_length++;
}
if (nums[i] < nums[i - 1]) {
STATE = DOWN;
max_length++;
}
break;
case UP:
if (nums[i] < nums[i - 1]) {
STATE = DOWN;
max_length++;
}
break;
case DOWN:
if (nums[i - 1] < nums[i]) {
STATE = UP;
max_length++;
}
break;
default:
break;
}
}
return max_length;
}