最长湍流子数组
当 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)
马上过年啦,我在这里提前祝大家新年快乐哦!!!!