978. 最长湍流子数组(滑动窗口)

17 篇文章 0 订阅
15 篇文章 0 订阅
本文介绍了如何找到整数数组的最大湍流子数组长度。通过使用双指针滑动窗口的方法,我们可以有效地遍历数组,确定每个元素是否满足湍流子数组的条件。在遍历过程中,当遇到相邻元素相等时,左指针移动,否则根据条件更新右指针。最终返回最大湍流子数组的长度。这种方法的时间复杂度为O(n),空间复杂度为O(1)。
摘要由CSDN通过智能技术生成

最长湍流子数组

当 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


解题思路

由于题中提到了子区间/子数组,所以该题与滑动窗口的题目类似。
首先,我们先设置两个指针 left 和 right (其中 right 是主动右移,遍历整个 arr 数组),分别指向数组 arr 的开头。

  • 当两个指针指向的位置相同时:其中的 right 指针是必须向右移动的(在进行第一次比较时,right 的值一定是等于 1 的),但 left 指针仅在两个相邻元素的值相等时才向右移动(因为若有两个相邻的元素值相等,则这个子数组一定不是湍流子数组[要求:相邻的两个元素之间的关系要么是 “>” 要么是 “<”,没有 “=”])。
  • 当两个指针指向的位置不同时:当 right 位置上的元素值与 right + 1 和 right - 1 位置上的元素值比较后是最大值或最小值时。此时,arr[right - 1]、arr[right]、arr[right + 1] 一定是符合湍流子数组要求的,right 指针直接向右移动。除这两个条件之外的其他所有条件,都是不符合湍流子数组要求的,此时应把 left 指针直接移动到 right 指针的位置,相当于直接从当前 right 指针的位置重新开始寻找湍流子数组。

注意:在两个指针位置不同时,比较的应该是数组中 right - 1,right 和 right + 1 位置上的元素值,而不能是 right,right + 1 和 right + 2 位置上的元素。因为,在一开始时 left == right,在经过一次的执行后 right 的值变为 1。如果比较 right,right + 1 和 right + 2 位置上的元素,则就无法操作到数组中第一个元素了,所以,应将第一个 right 改为 right - 1,以此类推。

有比较数组中相邻的三个位置上的元素值时—尽量使用的元素下标为 i - 1,i 和 i + 1.


代码

class Solution {

    //有子数组----滑动窗口
    /*
        双指针:left和right--从左向右移动(右:主动;left:被动))
        1.只要遇到相同的连续的元素,left在记录下之前的窗口长度后直接右移,右指针右移
        2.遇到9 4 2--->9 > 4 > 2 或 2 4 9 --->2 < 4< 9 不需要用它们来当做条件来判断放在一起
        3.还有特殊区间长度为1--->right = left
          - 滑动窗口的大小:right - left + 1
    */
    public int maxTurbulenceSize(int[] arr) {

        int n = arr.length;
        int left = 0, right = 0;
        //当数组中只有一个元素时,是不进while循环的但又满足条件,所以直接设置为1
        int maxLength = 1;
        while (right < n - 1) {

            if (left == right) {

                right++;
                //只有相邻的两个元素相等时left才 + 1  否则只有右指针移动
                if (arr[left] == arr[left + 1]) {

                    left++;
                }
            } else {

                /*
                因为一开始right==left 经过一次执行后 right变为1 
                若看right right+1 right+2则无法操作到第一个元素了---将right改为right-1
                */
                if (arr[right - 1] < arr[right]&&arr[right] > arr[right + 1]) {

                    right++;
                } else if (arr[right - 1] > arr[right]&&arr[right] < arr[right + 1]) {

                    right++;
                } else { //别的条件都是不符合要求的---直接从新开始

                    left = right;
                }
            }
            maxLength = Math.max(maxLength, right - left + 1);
        }
        return maxLength;
    }
}

时间复杂度:因为数组 arr 的长度为n,并且只遍历了一次数组,复杂度为O(n)
空间复杂度:O(1)


马上过年啦,我在这里提前祝大家新年快乐哦!!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值