PigyChan_LeetCode 978. 最长湍流子数组

978. 最长湍流子数组

当 A 的子数组 A[i], A[i+1], …, A[j] 满足下列条件时,我们称其为湍流子数组: * 若 i <= k < j,当 k 为奇数时, A[k] > A[k+1],且当 k 为偶数时,A[k] < A[k+1]; * 或 若 i <= k < j,当 k 为偶数时,A[k] > A[k+1] ,且当 k 为奇数时, A[k] < A[k+1]。
也就是说,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是湍流子数组。 返回 A 的最大湍流子数组的长度。 示例 1:
输入:[9,4,2,10,7,8,8,1,9] 输出:5 解释:(A[1] > A[2] < A[3] > A[4] < A[5]) 示例 2:
输入:[4,8,12,16] 输出:2 示例 3:
输入:[100] 输出:1

个人思路:
在这里插入图片描述

代码1.0

class Solution {
public:
    int maxTurbulenceSize(vector<int>& A) {
        int len = A.size();
        if(len==0)
        {
            return 0;
        }
        if(len==1)
        {
            return 1;
        }
        int value = A[0];
        if(len == count(A.begin(),A.end(),value))
        {
            return 1;
        }


        vector<int> dp(len,1);
        int conti=0;


        for(int i=1;i<len-1;++i)
        {
            if((A[i-1]>=A[i]&&A[i]>=A[i+1])||(A[i-1]<=A[i]&&A[i]<=A[i+1]))
            {
                dp[i+1]=dp[i];
                conti = 0;
            }


            if((A[i-1]>A[i]&&A[i]<A[i+1])||(A[i-1]<A[i]&&A[i]>A[i+1]))
            {
                if(++conti+2 < dp[i])
                {
                    dp[i+1]=dp[i];
                }
                else
                {
                    dp[i+1]=max(dp[i]+1,conti+2);   
                }


            }
        }


        return dp[len-1]<2?2:dp[len-1];
    }
};

题解思路:
如果 f(k-1)f(k−1) 波形数组的最后一段是“上升”,且 A[k-1] 和 A[k-2] 之间是“上升”,那么 f(k) = 2f(k)=2;
如果 f(k-1)f(k−1) 波形数组的最后一段是“上升”,且 A[k-1] 和 A[k-2] 之间是“下降”,那么 f(k) = f(k-1) + 1f(k)=f(k−1)+1;
如果 f(k-1)f(k−1) 波形数组的最后一段是“下降”,且 A[k-1] 和 A[k-2] 之间是“上升”,那么 f(k) = f(k-1) + 1f(k)=f(k−1)+1;
如果 f(k-1)f(k−1) 波形数组的最后一段是“下降”,且 A[k-1] 和 A[k-2] 之间是“下降”,那么 f(k) = 2f(k)=2;
如果 A[k-1] 和 A[k-2] 之间是“水平”,那么 f(k) = 1f(k)=1;
什么?一个看似简单的问题竟然要分这么多情况考虑,是不是看得头都大了?

通常来说,如果你发现子问题的递推关系过于复杂,那可能是子问题定义得不是很好。既然我们总是要判断波形数组的最后一段是上升还是下降,那我们为何不在子问题定义时就把它们区分开来呢?

是的,我们可以定义两个子问题,分别对应最后一段上升和下降的波形子数组:

子问题 f(k)f(k) 为数组 A[0…k) 中,以 A[k-1] 结尾,且最后一段为“上升”的最长波形子数组;
子问题 g(k)g(k) 为数组 A[0…k) 中,以 A[k-1] 结尾,且最后一段为“下降”的最长波形子数组。
那么我们的子问题递推关系就变得清晰了起来:

如果 A[k-1] 和 A[k-2] 之间是“上升”,那么 f(k) = g(k-1) + 1f(k)=g(k−1)+1,g(k) = 1g(k)=1;
如果 A[k-1] 和 A[k-2] 之间是“下降”,那么 f(k) = 1f(k)=1,g(k) = f(k-1) + 1g(k)=f(k−1)+1;
如果 A[k-1] 和 A[k-2] 之间是“水平”,那么 f(k) = 1f(k)=1,g(k) = 1g(k)=1。

*当子问题非常复杂时,可将子问题分解。

代码2.0:

class Solution {
public:
    int maxTurbulenceSize(vector<int>& A) {
        int len = A.size();
        if (len <= 1 )
        {
            return len;
        }


        vector<int> up(len+1, 0);
        vector<int> down(len+1, 0);
        up[1] = 1;
        down[1] = 1;


        int res = 1;


        for (int i = 2; i <= len; ++i)
        {
            if (A[i - 2] < A[i-1])
            {
                up[i] = down[i - 1] + 1;
                down[i] = 1;
            }


            if (A[i - 2] > A[i-1])
            {
                up[i] = 1;
                down[i] = up[i - 1] + 1;
            }


            if (A[i - 2] == A[i-1])
            {
                up[i ] = 1;
                down[i ] = 1;
            }


            res = max(res, up[i]);
            res = max(res, down[i]);
        }


        return res;
    }
};

res=max(res,up[i])和res=max(res,down[i]);在历次迭代中保存湍流长度的最大值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值