3105. Longest Strictly Increasing or Strictly Decreasing Subarray - Explanation
Description
You are given an array of integers nums. Return the length of the longest subarray of nums which is either strictly increasing or strictly decreasing.
Note:
- An array is said to be strictly increasing if each element is strictly greater than its previous one (if exists).
- An array is said to be strictly decreasing if each element is strictly smaller than its previous one (if exists).
Example 1:
Input: nums = [1,4,3,3,2]
Output: 2Explanation: The strictly increasing subarrays of nums are [1], [2], [3], [3], [4], and [1,4].
The strictly decreasing subarrays of nums are [1], [2], [3], [3], [4], [3,2], and [4,3].
Hence, we return 2.
Example 2:
Input: nums = [3,3,3,3]
Output: 1Explanation: The strictly increasing subarrays of nums are [3], [3], [3], and [3].
The strictly decreasing subarrays of nums are [3], [3], [3], and [3].
Hence, we return 1.
Example 3:
Input: nums = [3,2,1]
Output: 3Explanation: The strictly increasing subarrays of nums are [3], [2], and [1].
The strictly decreasing subarrays of nums are [3], [2], [1], [3,2], [2,1], and [3,2,1].
Hence, we return 3.
Constraints:
1 <= nums.length <= 501 <= nums[i] <= 50
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Array Traversal - Iterating through arrays and comparing adjacent elements
- Basic Iteration Patterns - Tracking running counters and updating maximum values during a single pass
- Monotonic Sequences - Understanding strictly increasing and strictly decreasing patterns and how they break
1. Brute Force
Intuition
The straightforward approach is to check every possible starting position and see how far we can extend a monotonic subarray from there. For each starting index, we determine if the subarray is increasing or decreasing based on the first two elements, then continue as long as the pattern holds.
Algorithm
- Initialize
res = 1to track the maximum length found. - For each starting index
ifrom0ton-2:- Start with
curLen = 1. - Determine if the subarray starting at
iis increasing or decreasing. - Extend
jfromi+1while the pattern continues (strictly increasing or strictly decreasing). - Update
reswith the maximum ofresandcurLen.
- Start with
- Return
res.
class Solution:
def longestMonotonicSubarray(self, nums: List[int]) -> int:
n = len(nums)
res = 1
for i in range(n - 1):
curLen = 1
for j in range(i + 1, n):
if nums[j] == nums[j - 1] or ((nums[i] < nums[i + 1]) != (nums[j - 1] < nums[j])):
break
curLen += 1
res = max(res, curLen)
return resTime & Space Complexity
- Time complexity:
- Space complexity:
2. Iteration - I
Intuition
We can solve this in a single pass by tracking the current monotonic subarray's length and direction. As we scan through the array, we check if the current element continues the same pattern (increasing or decreasing). If it does, we extend the current subarray. If not, we start a new subarray with the current pair of elements.
Algorithm
- Initialize
cur = 1(current subarray length),res = 1(result), andincreasing = 0(direction flag). - For each index
ifrom1ton-1:- If
nums[i-1] < nums[i](increasing):- If already in increasing mode, increment
cur. - Otherwise, reset
cur = 2and setincreasing = 1.
- If already in increasing mode, increment
- Else if
nums[i-1] > nums[i](decreasing):- If already in decreasing mode, increment
cur. - Otherwise, reset
cur = 2and setincreasing = -1.
- If already in decreasing mode, increment
- Else (equal elements): reset
cur = 1andincreasing = 0. - Update
res = max(res, cur).
- If
- Return
res.
class Solution:
def longestMonotonicSubarray(self, nums: List[int]) -> int:
cur = 1
res = 1
increasing = 0
for i in range(1, len(nums)):
if nums[i - 1] < nums[i]:
if increasing > 0:
cur += 1
else:
cur = 2
increasing = 1
elif nums[i - 1] > nums[i]:
if increasing < 0:
cur += 1
else:
cur = 2
increasing = -1
else:
cur = 1
increasing = 0
res = max(res, cur)
return resTime & Space Complexity
- Time complexity:
- Space complexity:
3. Iteration - II
Intuition
A cleaner approach is to maintain two separate counters: one for the current strictly increasing subarray length and one for the current strictly decreasing subarray length. At each step, we update both counters based on the relationship between consecutive elements.
Algorithm
- Initialize
inc = 1,dec = 1(current lengths), andres = 1(result). - For each index
ifrom1ton-1:- If
nums[i] == nums[i-1]: reset bothinc = 1anddec = 1. - Else if
nums[i] > nums[i-1]: incrementinc, resetdec = 1. - Else: increment
dec, resetinc = 1. - Update
res = max(res, inc, dec).
- If
- Return
res.
class Solution:
def longestMonotonicSubarray(self, nums: List[int]) -> int:
inc = dec = 1
res = 1
for i in range(1, len(nums)):
if nums[i] == nums[i - 1]:
inc = dec = 1
elif nums[i] > nums[i - 1]:
inc, dec = inc + 1, 1
else:
inc, dec = 1, dec + 1
res = max(res, inc, dec)
return resTime & Space Complexity
- Time complexity:
- Space complexity:
4. Iteration - III
Intuition
Another variation uses a single counter and checks if the current direction matches the direction at the start of the current subarray. By comparing the relationship between elements at the subarray's start with the relationship at the current position, we can determine if we're still following the same monotonic pattern.
Algorithm
- Initialize
curLen = 1andres = 1. - For each index
ifrom1ton-1:- If elements are equal, or if the direction at position
i-curLendiffers from the direction at positioni-1:- Reset
curLento1(if equal) or2(if different direction). - Continue to the next iteration.
- Reset
- Otherwise, increment
curLenand updateres = max(res, curLen).
- If elements are equal, or if the direction at position
- Return
res.
class Solution:
def longestMonotonicSubarray(self, nums: List[int]) -> int:
curLen = res = 1
for i in range(1, len(nums)):
if (nums[i] == nums[i - 1] or
((nums[i - curLen] < nums[i - curLen + 1]) != (nums[i - 1] < nums[i]))
):
curLen = 1 if (nums[i] == nums[i - 1]) else 2
continue
curLen += 1
res = max(res, curLen)
return resTime & Space Complexity
- Time complexity:
- Space complexity:
Common Pitfalls
Ignoring Equal Consecutive Elements
The problem asks for strictly increasing or strictly decreasing subarrays. Equal consecutive elements (nums[i] == nums[i-1]) break both patterns. A common mistake is treating equal elements as continuing the current sequence. When you encounter equal elements, you must reset your counter to 1 because a single element is a valid subarray of length 1.
Forgetting to Track Both Directions
You need to find the longest subarray that is either strictly increasing OR strictly decreasing. A common error is only tracking one direction and missing the optimal answer. Either maintain two separate counters (one for increasing, one for decreasing) or use a direction flag that resets when the pattern changes.
Sign in to join the discussion