1. 题目链接:978. 最长湍流子数组
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 * 104
0 <= arr[i] <= 109
3. 解法(动态规划):
3.1 算法思路:
1. 状态表示:
f[i]
表示:以i
位置元素为结尾的所有子数组中,最后呈现上升状态下的最长湍流数组的长度
g[i]
表示:以i
位置元素为结尾的所有子数组中,最后呈现下降状态下的最长湍流数组的长度
2. 状态转移方程:
对于i
位置的元素 arr[i]
,又下面两种情况:
arr[i]>arr[i-1]
:如果i
位置的元素比i-1
位置的元素大,说明接下来应该去找i-1
位置结尾,并且i-1
位置元素比前面一个元素小的序列,那就是g[i-1]
,更新f[i]
位置的值:f[i]=g[i-1]+1
arr[i]<arr[i-1]
:如果i
位置的元素比i-1
位置元素小,说明接下来应该找i-1
位置结尾,并且i-1
位置元素比前一个元素大的序列,那就是f[i-1]
。更新g[i]
位置的值:g[i]=f[i-1]+1
arr[i]=arr[i-1]
:不构成湍流数组
3. 初始化:
所有的元素单独都能构成一个湍流数组,因此可以将 dp
表内所有元素初始化为1
由于用到前面的状态,因此我们循环的时候从第二个位置开始即可
4. 填表顺序:
从左往右,两个表一起填
5. 返回值:
返回两个dp
表里面的最大值,我们可以在填表的时候,顺序更新一些最大值
3.2 C++算法代码:
class Solution {
public:
// 计算数组中最大的湍流子数组的长度
int maxTurbulenceSize(vector<int>& arr) {
int n = arr.size(); // 获取数组长度
vector<int> f(n, 1), g(n, 1); // 初始化两个辅助数组f和g,初始值都为1
int ret = 1; // 初始化最大湍流子数组长度为1
for (int i = 1; i < n; i++) {
// 如果当前元素大于前一个元素,更新f[i]
if (arr[i - 1] < arr[i]) {
f[i] = g[i - 1] + 1;
}
// 如果当前元素小于前一个元素,更新g[i]
else if (arr[i - 1] > arr[i]) {
g[i] = f[i - 1] + 1;
}
// 如果当前元素等于前一个元素,重置f[i]和g[i]为1
ret = max(ret, max(f[i], g[i])); // 更新最大湍流子数组长度
}
return ret; // 返回最大湍流子数组长度
}
};