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

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]

循环结构的代码

for(int i=2; iA[i-1]) 
        //如果满足,那么这个端流子数组可以直接扩展一个长度
        {
            dp[i] = dp[i-1]+1;
            flag = 0;//将flag置为0,表示A[i+1]应该小于A[i]
        }                
        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 = 0;
        }
        else
        {
            dp[i] = 1;
            flag = -1;
        }
        //这里的操作跟初始时一模一样
    }
    max = Math.max(max, dp[i]);
}

结果
最长端流子数组--动态规划_第1张图片

心得体会

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

题目来源于

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

你可能感兴趣的:(算法,leetcode,动态规划,java)