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
的最大湍流子数组的长度。
示例 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
提示:
1 <= A.length <= 40000
0 <= A[i] <= 10^9
方法一:强撸
解题思路
- 没有特别的技巧,遍历一次数组,依次比较数字,找出子数组长度
参考代码
public int maxTurbulenceSize(int[] arr) {
int n = arr.length, idx = 0;
int ret = 1, preState = 0;
for (int i = 1; i < n; i++) {
int state = Integer.compare(arr[i], arr[i - 1]);
if (state == preState || state == 0) {
ret = Math.max(ret, i - idx);
idx = state == 0 ? i : i - 1;
}
preState = state;
}
return Math.max(ret, n - idx);
}
执行结果
方法二:动态规划
解题思路
- 状态定义:每个角标有三种状态,分别是 上坡、下坡、平地(等于前面的数)
up[i]
表示索引i
为上坡时的子数组长度down[i]
表示索引i
为下坡时的子数组长度- 如果是平地,则
down[i] = up[i] = 1
- 初始化:令两个数组全部为
1
。 - 状态转移:
- 索引
i
是上坡:up[i] = down[i] + 1
- 索引
i
是下坡:down[i] = up[i] + 1
- 索引
i
是平地,不做任何操作(也可以不用初始化,在这里令down[i] = up[i] = 1
)
- 索引
参考代码
public int maxTurbulenceSize(int[] arr) {
int n = arr.length;
int[] up = new int[n], down = new int[n];
Arrays.fill(up, 1);
Arrays.fill(down, 1);
int ret = 1;
for (int i = 1; i < n; i++) {
if (arr[i] > arr[i - 1]) {
up[i] = down[i - 1] + 1;
} else if(arr[i] < arr[i - 1]) {
down[i] = up[i - 1] + 1;
}
ret = Math.max(ret, Math.max(up[i], down[i]));
}
return ret;
}
执行结果