24. 最长湍流子数组

1.题目链接:

978. 最长湍流子数组 - 力扣(LeetCode)978. 最长湍流子数组 - 给定一个整数数组 arr ,返回 arr 的 最大湍流子数组的长度 。如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是 湍流子数组 。更正式地来说,当 arr 的子数组 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]。 示例 1:输入:arr = [9,4,2,10,7,8,8,1,9]输出:5解释:arr[1] > arr[2] < arr[3] > arr[4] < arr[5]示例 2:输入:arr = [4,8,12,16]输出:2示例 3:输入:arr = [100]输出:1 提示: * 1 <= arr.length <= 4 * 104 * 0 <= arr[i] <= 109https://leetcode.cn/problems/longest-turbulent-subarray/description/2.题目描述:

给定一个整数数组 arr ,返回 arr 的 最大湍流子数组的长度 。​
    如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是 湍流子数组 。​
    更正式地来说,当 arr 的子数组 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]。​
     ​
    示例 1:​
    输入:arr = [9,4,2,10,7,8,8,1,9]​
    输出:5​
    解释:arr[1] > arr[2] < arr[3] > arr[4] < arr[5]​

示例 2:​
输入:arr = [4,8,12,16]​
输出:2​

示例 3:​
输入:arr = [100]​
输出:1​

提示:
1 <= arr.length <= 4 * 10^4​
0 <= arr[i] <= 10^9​

3. 解法(动态规划):
算法思路:
1. 状态表示:
        我们先尝试定义状态表示为:
          dp[i]  表示「以 i  位置为结尾的最长湍流数组的长度」。​
        但是,问题来了,如果状态表示这样定义的话,以 i  位置为结尾的最长湍流数组的长度我们没法            从之前的状态推导出来。因为我们不知道前一个最长湍流数组的结尾处是递增的,还是递减的。因                  此,我们需要状态表示能表示多一点的信息:要能让我们知道这一个最长湍流数组的结尾是「递                增」的还是「递减」的。

因此需要两个 dp  表:​
        f[i]  表示:以 i  位置元素为结尾的所有子数组中,最后呈现「上升状态」下的最长湍流数组的长度;
        g[i]  表示:以 i  位置元素为结尾的所有子数组中,最后呈现「下降状态」下的最长湍流数组的长度。

2. 状态转移方程:
        对于 i 位置的元素 arr[i] ,有下面两种情况:​

i.

arr[i] > arr[i - 1] :如果 i  位置的元素比 i - 1  位置的元素大,说明接下来

应该去找 i -1  位置结尾,并且 i - 1  位置元素比前一个元素小的序列,那就是 g[i - 1] 。更新 f[i]  位置的值:f[i] = g[i - 1] + 1 ;​

ii.

arr[i] < arr[i - 1] :如果 i  位置的元素比 i - 1  位置的元素小,说明接下来

应该去找 i - 1  位置结尾,并且 i - 1  位置元素比前一个元素大的序列,那就是 f[i - 1] 。更新 g[i]  位置的值:g[i] = f[i - 1] + 1 ;​

iii.

arr[i] == arr[i - 1] :不构成湍流数组。​

3. 初始化:

所有的元素「单独」都能构成一个湍流数组,因此可以将 dp  表内所有元素初始化为 1 。​

由于用到前面的状态,因此我们循环的时候从第二个位置开始即可。

4. 填表顺序:

毫无疑问是「从左往右,两个表一起填」。

5. 返回值:

应该返回「两个 dp  表里面的最大值」,我们可以在填表的时候,顺便更新一个最大值。​

Java算法代码:

class Solution {
    public int maxTurbulenceSize(int[] arr) {
        // 1. 创建dp表
        // 2.初始化
        // 3.填表
        // 4.返回值
        int n = arr.length;
        int[] f = new int[n];
        int[] g = new int[n];

        for(int i = 0; i < n; i++) f[i] = g[i] =1;

        int ret = 1;
        for(int i =1; i< n; i++){
            if(arr[i-1] < arr[i]) f[i] = g[i-1] + 1;
            else if(arr[i - 1] > arr[i]) g[i] = f[i - 1] + 1;
            ret = Math.max(ret, Math.max(f[i],g[i]));
        }
        return ret;
    }
}

运行结果:

动态规划:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值