3105. Longest Strictly Increasing or Strictly Decreasing Subarray
Problem Description
You are given an array of integers nums
. Your task is to return the length of the longest subarray of nums
which is either strictly increasing or strictly decreasing.
Intuition
To solve this problem, we need to identify the subarrays within nums
that are either strictly increasing or strictly decreasing. The goal is to find the length of the longest such subarray.
The approach involves a two-pass method:
-
First Pass: Finding Increasing Subarrays
- Start with an initial length
t
of 1 for a potential subarray. - Traverse the array from the second element, comparing each element with the previous one.
- If the current element is greater than the previous, it indicates a continuation of an increasing sequence, so we increase
t
. - If the current element is not greater, the increasing streak is broken, and
t
is reset to 1. - Keep track of the maximum length encountered using the
ans
variable.
- Start with an initial length
-
Second Pass: Finding Decreasing Subarrays
- Reset
t
and repeat the process, this time looking for strictly decreasing sequences. - If the current element is less than the previous, increase
t
. - If not, reset
t
to 1, as the sequence has ended. - Again, update
ans
to capture the longest decreasing sequence found.
- Reset
After both passes, ans
will contain the length of the longest monotonic subarray, whether increasing or decreasing.
Solution Approach
The solution is structured into two primary passes through the nums
array, utilizing a linear scan approach. Here's how we execute the solution:
-
Initial Setup:
- Initialize
ans
to store the maximum length found, andt
to store the current subarray length, both starting at 1.
- Initialize
-
First Pass: Strictly Increasing Subarray:
- Traverse
nums
from index 1 to the end. - Compare each element
x
with the previous element:- If
x > nums[i]
, it indicates the subarray is strictly increasing, so incrementt
. - If
x <= nums[i]
, resett
to 1 to start a new potential increasing subarray.
- If
- Update
ans
with the maximum of its current value andt
.
- Traverse
for i, x in enumerate(nums[1:]):
if nums[i] < x:
t += 1
ans = max(ans, t)
else:
t = 1
-
Reset for Second Pass:
- Set
t
back to 1 to compute decreasing subarray lengths anew.
- Set
-
Second Pass: Strictly Decreasing Subarray:
- Again, traverse
nums
, comparing each elementx
with the one before:- If
x < nums[i]
, incrementt
indicating the array is decreasing. - Otherwise, reset
t
to 1.
- If
- Update
ans
similarly with any longer decreasing subarray discovered.
- Again, traverse
t = 1
for i, x in enumerate(nums[1:]):
if nums[i] > x:
t += 1
ans = max(ans, t)
else:
t = 1
- Conclusion:
- After both passes,
ans
holds the length of the longest subarray that is either strictly increasing or strictly decreasing, effectively solving the problem.
- After both passes,
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's illustrate the solution approach with an example. Consider the array nums = [3, 8, 5, 7, 6, 2, 4, 1]
. Our goal is to find the length of the longest subarray that is either strictly increasing or strictly decreasing.
Step 1: Initial Setup
- Initialize
ans
to 1, which holds the maximum length found. - Initialize
t
to 1, which holds the current subarray length.
Step 2: First Pass for Increasing Subarrays
- Start traversing
nums
from the second element (index 1).
-
Index 1: Compare
8
with3
.- Since
8 > 3
, the sequence is increasing. Incrementt
to 2. - Update
ans
to the maximum ofans
andt
, which is now 2.
- Since
-
Index 2: Compare
5
with8
.- Since
5 <= 8
, resett
to 1.
- Since
-
Index 3: Compare
7
with5
.- Since
7 > 5
, incrementt
to 2. ans
remains 2, as it is still the maximum.
- Since
-
Index 4: Compare
6
with7
.- Since
6 <= 7
, resett
to 1.
- Since
-
Index 5: Compare
2
with6
.- Since
2 <= 6
,t
remains 1.
- Since
-
Index 6: Compare
4
with2
.- Since
4 > 2
, incrementt
to 2.
- Since
-
Index 7: Compare
1
with4
.- Since
1 <= 4
, resett
to 1.
- Since
After the first pass, the longest increasing subarray has length 2 ([3, 8]
, [5, 7]
, or [2, 4]
).
Step 3: Reset for Second Pass
- Reset
t
to 1 to check for decreasing subarrays.
Step 4: Second Pass for Decreasing Subarrays
- Traverse
nums
starting from index 1 again, but this time look for decreasing subarrays.
-
Index 1: Compare
8
with3
.- Since
8 <= 3
,t
remains 1.
- Since
-
Index 2: Compare
5
with8
.- Since
5 < 8
, incrementt
to 2. - Update
ans
to the maximum ofans
andt
, which is now 2.
- Since
-
Index 3: Compare
7
with5
.- Since
7 >= 5
, resett
to 1.
- Since
-
Index 4: Compare
6
with7
.- Since
6 < 7
, incrementt
to 2. ans
remains 2.
- Since
-
Index 5: Compare
2
with6
.- Since
2 < 6
, incrementt
to 3. - Update
ans
to 3, which is now the maximum.
- Since
-
Index 6: Compare
4
with2
.- Since
4 >= 2
, resett
to 1.
- Since
-
Index 7: Compare
1
with4
.- Since
1 < 4
, incrementt
to 2.
- Since
After the second pass, the longest decreasing subarray is [7, 6, 2]
with a length of 3.
Step 5: Conclusion
- The longest subarray that is either strictly increasing or strictly decreasing has a length of 3, which is
[7, 6, 2]
.
Solution Implementation
1from typing import List
2
3class Solution:
4 def longestMonotonicSubarray(self, nums: List[int]) -> int:
5 # Initialize the maximum length of monotonic subarray
6 # and current increasing sequence length
7 ans = increasing_length = 1
8
9 # Iterate through the array to find the longest increasing subarray
10 for i, num in enumerate(nums[1:], start=1):
11 if nums[i - 1] < num: # Check if current number is greater than the previous
12 increasing_length += 1
13 ans = max(ans, increasing_length) # Update the maximum length found so far
14 else:
15 increasing_length = 1 # Reset the length for new increasing sequence
16
17 # Reset the current decreasing sequence length
18 decreasing_length = 1
19
20 # Iterate through the array again to find the longest decreasing subarray
21 for i, num in enumerate(nums[1:], start=1):
22 if nums[i - 1] > num: # Check if current number is less than the previous
23 decreasing_length += 1
24 ans = max(ans, decreasing_length) # Update the maximum length found so far
25 else:
26 decreasing_length = 1 # Reset the length for new decreasing sequence
27
28 return ans # Return the maximum length of a monotonic subarray found
29
1class Solution {
2 public int longestMonotonicSubarray(int[] nums) {
3 int longestLength = 1; // Initialize the maximum length of monotonic subarray
4
5 // Find the longest increasing subarray
6 for (int i = 1, currentLength = 1; i < nums.length; ++i) {
7 if (nums[i - 1] < nums[i]) {
8 // If current element is greater than the previous, increase the current length
9 currentLength++;
10 // Update the longest length if current length exceeds it
11 longestLength = Math.max(longestLength, currentLength);
12 } else {
13 // Reset current length when the increasing sequence breaks
14 currentLength = 1;
15 }
16 }
17
18 // Find the longest decreasing subarray
19 for (int i = 1, currentLength = 1; i < nums.length; ++i) {
20 if (nums[i - 1] > nums[i]) {
21 // If current element is less than the previous, increase the current length
22 currentLength++;
23 // Update the longest length if current length exceeds it
24 longestLength = Math.max(longestLength, currentLength);
25 } else {
26 // Reset current length when the decreasing sequence breaks
27 currentLength = 1;
28 }
29 }
30
31 // Return the longest length found
32 return longestLength;
33 }
34}
35
1#include <vector>
2#include <algorithm>
3
4class Solution {
5public:
6 int longestMonotonicSubarray(std::vector<int>& nums) {
7 int longestSubarray = 1; // This variable will hold the length of the longest monotonic subarray.
8
9 // Check for increasing subarrays
10 for (int i = 1, currentLength = 1; i < nums.size(); ++i) {
11 if (nums[i - 1] < nums[i]) {
12 // If the current number is greater than the previous, increase the length of the current increasing subarray.
13 longestSubarray = std::max(longestSubarray, ++currentLength);
14 } else {
15 // Reset the length as the sequence is no longer increasing.
16 currentLength = 1;
17 }
18 }
19
20 // Check for decreasing subarrays
21 for (int i = 1, currentLength = 1; i < nums.size(); ++i) {
22 if (nums[i - 1] > nums[i]) {
23 // If the current number is less than the previous, increase the length of the current decreasing subarray.
24 longestSubarray = std::max(longestSubarray, ++currentLength);
25 } else {
26 // Reset the length as the sequence is no longer decreasing.
27 currentLength = 1;
28 }
29 }
30
31 return longestSubarray; // Return the length of the longest monotonic subarray found.
32 }
33};
34
1function longestMonotonicSubarray(nums: number[]): number {
2 let ans = 1; // Initialize the answer variable to 1 as any single element is a monotonic subarray
3
4 // Check for increasing subarrays
5 for (let i = 1, currentLength = 1; i < nums.length; ++i) {
6 if (nums[i - 1] < nums[i]) {
7 // Increase current length if current number is greater than the previous one
8 currentLength++;
9 // Update ans if the current increasing subarray is the longest found so far
10 ans = Math.max(ans, currentLength);
11 } else {
12 // Reset current length if the sequence breaks
13 currentLength = 1;
14 }
15 }
16
17 // Check for decreasing subarrays
18 for (let i = 1, currentLength = 1; i < nums.length; ++i) {
19 if (nums[i - 1] > nums[i]) {
20 // Increase current length if current number is less than the previous one
21 currentLength++;
22 // Update ans if the current decreasing subarray is the longest found so far
23 ans = Math.max(ans, currentLength);
24 } else {
25 // Reset current length if the sequence breaks
26 currentLength = 1;
27 }
28 }
29
30 return ans; // Return the length of the longest monotonic subarray found
31}
32
Time and Space Complexity
The time complexity of the code is O(n)
, where n
is the length of the array. This is because the algorithm iterates through the list twice, each one being a linear scan.
The space complexity is O(1)
, as the algorithm uses a constant amount of extra space regardless of the input size. It only requires a few integer variables (ans
and t
) for its operations.
Learn more about how to find time and space complexity quickly.
How would you design a stack which has a function min
that returns the minimum element in the stack, in addition to push
and pop
? All push
, pop
, min
should have running time O(1)
.
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!