https://leetcode-cn.com/problems/longest-turbulent-subarray/
当 A 的子数组 A[i], A[i+1], …, A[j] 满足下列条件时,我们称其为湍流子数组:
也就是说,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是湍流子数组。
返回 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
我的想法属于变相暴力吧,题目的意思就是符号一大一小或者一小一大下去,找最长的。
在原数组的基础上,开辟一个N-1大小的数组,存储两两对应关系
然后在这个全是-1,0,1的数组里面,找到最长的一个串(1-11-1或者-11-11这样的串)。遍历一遍即可找到(其实不开数组也能找到)
public class Solution_978 {
public static void main(String[] args) {
// System.out.println(maxTurbulenceSize(new int[]{9, 4, 2, 10, 7, 8, 8, 1, 9}));
System.out.println(maxTurbulenceSize(new int[]{
2, 0, 2, 4, 2, 5, 0, 1, 2, 3}));
}
public static int maxTurbulenceSize(int[] A) {
if (A.length == 1) {
// 只有一个数字,那直接返回1
return 1;
}
int[] help = new int[A.length - 1];
for (int i = 0; i < A.length - 1; i++) {
if (A[i] < A[i + 1]) {
help[i] = -1;
} else if (A[i] > A[i + 1]) {
help[i] = 1;
} else {
help[i] = 0;
}
}
int i = 0, j; // i是起始端点
int max = 0; // 最长长度
for (j = 1; j < help.length; j++) {
if (help[i] == 0) {
i = j; // 如果相等,则移动i指针到当前位置
continue;
}
// help[j] 一定是1或者-1
if (help[j] * help[j - 1] == 1 || help[j] * help[j - 1] == 0) {
i = j; // 如果相同或者是0,则把i更新到此位置
continue;
} else if (help[j] * help[j - 1] == -1) {
max = Math.max(j - i + 1, max); // 对比max
continue;
}
}
if (max == 0) {
if (help[0] == 1 || help[0] == -1) return 2; // 数字长度大于2,且单调,返回2
return 1; // 数字长度大于2,且全部相等,返回1
}
return max + 1;
}
}
其实只和上次的符号有关,这样就不用开数组了,定义一个变量保存上次的符号即可。
private static int maxTurbulenceSize(int[] A) {
int pre_len = 1, ans = 1;
char pre = '=';
for (int i = 1; i < A.length; ++i) {
if (A[i] == A[i - 1]) {
// 相等
pre_len = 1; // 一旦相等就从1开始
pre = '=';
} else if (A[i] > A[i - 1] && pre == '<' || A[i] < A[i - 1] && pre == '>') // 交错
pre_len += 1;
else {
// 单调或上次是等号
pre_len = 2; // 一旦单调就从2开始
}
pre = A[i] > A[i - 1] ? '>' : '<'; // 更新上次符号
ans = Math.max(ans, pre_len); // 记录大小
}
return ans;
}
其中,值得注意的是:
单调
或上次符号是等号且这次单调
,长度从2开始计算