今天看到了一道有意思的解法,记录一下。
题目如下:
leetcode 376.摆动序列
分析一下[1,17,5,10,13,15,10,5,16,8],对于前3个元素是满足摆动序列要求的,而对于第4到6个元素,均为递增,所以摆动序列有以下几种情况:
[1,17,5,10…]
[1,17,5,13…]
[1,17,5,15…]
关于第四个元素的选择,可以使用贪心思想,让第四个元素尽可能的大,这样和第5个元素形成负数差的概率越大。
将上述数组转换为折线图,如下:
按照刚刚的分析,每次在连续递增和递减序列中,选择最末端的点就可以满足我们的需要。
因为这里只需要求出最大子序列长度,所以我们可以考虑将整个数组元素的状态分为三种:初始状态BEGIN、上升状态UP、下降状态DOWN,每次从BEGIN->UP/BEGIN->DOWN/UP->DOWN/->DOWN->UP最大子序列长度就会加1,状态机如下:
比如子数组[5,10,13,15],其实不用等到指针遍历到15时才更新maxLength,只需要在元素10时判断到上升趋势,就将maxLength+1。
状态机适用于判断条件较多的情况,这样代码会比较清晰。
代码如下:
class Solution {
static final int BEGIN = 1;
static final int UP = 2;
static final int DOWN = 3;
public int wiggleMaxLength(int[] nums) {
if (nums.length < 2) return nums.length;
int state = BEGIN;
int res = 1;
for (int i = 1; i < nums.length; i++) {
switch (state) {
case BEGIN:
if (nums[i] < nums[i - 1]) {//BEING->DOWN
state = DOWN;
res++;
} else if (nums[i] > nums[i - 1]) {BEING->UP
state = UP;
res++;
}
break;
case UP:
if (nums[i] < nums[i - 1]) {//UP->DOWN
state = DOWN;
res++;
}
break;
case DOWN:
if (nums[i] > nums[i - 1]) {//DOWN->UP
state = UP;
res++;
}
}
}
return res;
}
}