最长端流子数组--动态规划

leetcode 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的最大湍流子数组的长度。

解法:动态规划

解题思路: 这道题要我们找到一个子数组,该子数组所有两个相邻的数据是一大一小的,因此我们可以用一个一维的dp数组,该数组的含义是,以它为最后的一个数字的端流子数组的长度,因此我们可以得到一个动态转移方程

dp[i] = dp[i-1]+1,当A[i]跟前面A[i-1]能够形成端流子数组时
dp[i] = 2, 如果跟前面的无法形成端流子数组,但是跟前面的值不相等,那就跟前面一个数重新组成端流子数组
dp[i] = 1, 如果A[i]跟前面的值相同,那这时候要跟前面组成端流子数组也没办法了,因此dp[i]只能等于1

我们看一下代码实现部分,首先我们需要定义一个flag标志数字,flag的含义为A[i]应该小于A[i-1] (当flag=0)还是大于A[i-1] (当flag=1),当A[i-1] == A[i-2] 时,我们将flag置为-1,表示我们不知道应该将flag置为多少,让A[i]跟A[i-1]比较后重新判断

首先初始化

dp[0] = 1; //首先,第一个数字满足端流子数组,所以初始化为1
if(A[1]>A[0]) 
//如果A[1]大于A[0],那A[2]应该小于A[1],所以我们将flag置为0,0表示小于
{
    flag=0;
    dp[1]=2;
}           
else if(A[1]<A[0])同理,flag=1表示大于
{
    flag=1;
    dp[1]=2;
}
else 
//如果A[0]==A[1],那这两个数字没办法构成端流子数组,所以flag置为-1,-1表示A[2]得重新判断应该将flag置为多少
{
    flag=-1;
    dp[1]=1;
}

循环结构的代码

for(int i=2; i<A.length; i++)
//从数字第二个位置开始遍历
{
    if(flag==1)
    //如果flag==1,表示A[i]应该大于A[i-1]
    {
        if(A[i]>A[i-1]) 
        //如果满足,那么这个端流子数组可以直接扩展一个长度
        {
            dp[i] = dp[i-1]+1;
            flag = 0;//将flag置为0,表示A[i+1]应该小于A[i]
        }                
        else if(A[i]<A[i-1])
        //如果不满足,那就舍弃前面积累的端流子数组长度,直接以A[i]和A[i-1]组成一个新的端流子数组,这时候flag不用改变,因为A[i]和A[i-1]不满足flag,下一个应该满足
            dp[i] = 2;
        else
        //如果A[i-1]和A[i]相等,这时候我们没办法组成一个新的端流子数组,所以dp[i]=1,同时不知道下一个数应该是大于dp[i]还是小于dp[i],所以将flag置为-1,要进行类似于初始化时的动作
        {
            dp[i] = 1;
            flag = -1;
        }
    }
    else if(flag==0)
    //道理同上
    {
        if(A[i]<A[i-1])
        {
            dp[i] = dp[i-1]+1;
            flag = 1;
        }
        else if(A[i]>A[i-1])
            dp[i] = 2;
        else
        {
            dp[i] = 1;
            flag = -1;
        }
    }
    else // flag=-1,重新判断flag
    {
        if(A[i]<A[i-1])
        {
            dp[i] = dp[i-1]+1;
            flag = 1;
        }
        else if(A[i]>A[i-1])
        {
            dp[i] = dp[i-1]+1;
            flag = 0;
        }
        else
        {
            dp[i] = 1;
            flag = -1;
        }
        //这里的操作跟初始时一模一样
    }
    max = Math.max(max, dp[i]);
}

结果
在这里插入图片描述

心得体会

这次是唯一一次自己做出来的,之前做了十几道题,总是想不出来,都快怀疑自己做题有没有用了,这次是一次提交一次过,算是有进步了^_^

题目来源于

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-turbulent-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值