class Solution:
def maxTurbulenceSize(self, arr):
n = len(arr)
if n == 1:
return 1
max_len = 1
inc = dec = 1
for i in range(1, n):
if arr[i] > arr[i-1]:
inc = dec + 1
dec = 1
elif arr[i] < arr[i-1]:
dec = inc + 1
inc = 1
else:
inc = dec = 1
max_len = max(max_len, inc, dec)
return max_len
class Solution {
public:
int maxTurbulenceSize(vector<int>& arr) {
int n = arr.size();
if (n == 1) return 1;
int inc = 1, dec = 1, max_len = 1;
for (int i = 1; i < n; ++i) {
if (arr[i] > arr[i-1]) {
inc = dec + 1;
dec = 1;
} else if (arr[i] < arr[i-1]) {
dec = inc + 1;
inc = 1;
} else {
inc = dec = 1;
}
max_len = max(max_len, max(inc, dec));
}
return max_len;
}
};
class Solution {
public int maxTurbulenceSize(int[] arr) {
int n = arr.length;
if (n == 1) return 1;
int inc = 1, dec = 1, maxLen = 1;
for (int i = 1; i < n; i++) {
if (arr[i] > arr[i - 1]) {
inc = dec + 1;
dec = 1;
} else if (arr[i] < arr[i - 1]) {
dec = inc + 1;
inc = 1;
} else {
inc = dec = 1;
}
maxLen = Math.max(maxLen, Math.max(inc, dec));
}
return maxLen;
}
}
var maxTurbulenceSize = function(arr) {
let n = arr.length;
if (n === 1) return 1;
let inc = 1, dec = 1, maxLen = 1;
for (let i = 1; i < n; i++) {
if (arr[i] > arr[i - 1]) {
inc = dec + 1;
dec = 1;
} else if (arr[i] < arr[i - 1]) {
dec = inc + 1;
inc = 1;
} else {
inc = dec = 1;
}
maxLen = Math.max(maxLen, inc, dec);
}
return maxLen;
};
Given an integer array arr
, your task is to find the length of the longest subarray that is turbulent. A subarray is considered turbulent if the comparison signs between each adjacent pair of elements alternate between greater-than and less-than.
arr[i..j]
of length at least 2, for every k
in i <= k < j
:arr[k] > arr[k+1]
and arr[k+1] < arr[k+2]
and so on,arr[k] < arr[k+1]
and arr[k+1] > arr[k+2]
and so on.1 <= arr.length <= 4 * 10^4
0 <= arr[i] <= 10^9
You may not reuse elements (each subarray must be contiguous), and there is always at least one valid answer.
At first glance, the problem seems to ask for the longest contiguous subarray where the "up" and "down" relationships between consecutive elements alternate. A brute-force approach would check all possible subarrays, but with up to 40,000 elements, this is not feasible due to time constraints.
To optimize, we can notice that we only need to track the current "turbulent" streak as we scan the array. If the current comparison alternates from the previous one, we can extend the streak; otherwise, we reset. We can do this efficiently in a single pass.
This leads naturally to a sliding window or dynamic programming approach, where we keep counts of the current increasing and decreasing streaks.
We'll use a dynamic programming approach with two variables to represent the length of the current turbulent subarray ending at position i
:
i
where arr[i] > arr[i-1]
.
i
where arr[i] < arr[i-1]
.
inc = dec = 1
for the first element, since a single element is trivially a turbulent subarray of length 1.arr[i] > arr[i-1]
, increment inc
as dec + 1
(because we can extend a "down" streak), and reset dec
to 1.arr[i] < arr[i-1]
, increment dec
as inc + 1
, and reset inc
to 1.arr[i] == arr[i-1]
, reset both inc
and dec
to 1.This algorithm is efficient because it only needs a single pass and constant space.
Let's take arr = [9,4,2,10,7,8,8,1,9]
.
dec = inc + 1 = 2
, inc = 1
. Max so far: 2.dec = inc + 1 = 2
, inc = 1
. (Not turbulent, since two downs in a row.) Max remains 2.inc = dec + 1 = 3
, dec = 1
. Max so far: 3.dec = inc + 1 = 4
, inc = 1
. Max so far: 4.inc = dec + 1 = 5
, dec = 1
. Max so far: 5.dec = inc + 1 = 2
, inc = 1
. Max remains 5.inc = dec + 1 = 3
, dec = 1
. Max remains 5.
The answer is 5, corresponding to the subarray [4,2,10,7,8]
.
This efficiency is possible because the problem's nature allows us to make decisions based only on the last comparison, not the entire subarray.
In summary, the problem asks for the longest contiguous subarray with alternating up and down comparisons. By tracking the current increasing and decreasing streaks as we iterate, we can efficiently determine the answer in linear time. The key insight is to recognize the problem's alternating pattern and update our counters accordingly, avoiding unnecessary re-computation. The solution is elegant, efficient, and easy to implement.