在算法中使用状态机

今天看到了一道有意思的解法,记录一下。
题目如下:
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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值