medium Maximum Length of Semi-Decreasing Subarrays
Problem Statement
Given an integer array nums, return the length of the longest semi-decreasing subarray of nums, or 0 if there are no such subarrays.
If the first element is strictly greater than its last element for any array, it is semi-decreasing.
A subarray is a contiguous non-empty sequence of elements within an array.
Examples
-
Example 1:
- Input: nums =
[8, 4, 5, 3, 2] - Expected Output:
5 - Justification: The entire array is the largest segment where the first element (8) is greater than the last (2).
- Input: nums =
-
Example 2:
- Input: nums =
[1, 2, 3, 4, 5] - Expected Output:
0 - Justification: There's no segment where the starting number is greater than the ending number.
- Input: nums =
-
Example 3:
- Input: nums =
[1, 2, 12, 2, 5, 11, 13] - Expected Output:
4 - Justification: The largest semi-decreasing subarray is [12, 2, 5, 11].
- Input: nums =
Try it yourself
Try solving this question here:
✅ Solution Maximum Length of Semi-Decreasing Subarrays
Problem Statement
Given an integer array nums, return the length of the longest semi-decreasing subarray of nums, or 0 if there are no such subarrays.
If the first element is strictly greater than its last element for any array, it is semi-decreasing.
A subarray is a contiguous non-empty sequence of elements within an array.
Examples
-
Example 1:
- Input: nums =
[8, 4, 5, 3, 2] - Expected Output:
5 - Justification: The entire array is the largest segment where the first element (8) is greater than the last (2).
- Input: nums =
-
Example 2:
- Input: nums =
[1, 2, 3, 4, 5] - Expected Output:
0 - Justification: There's no segment where the starting number is greater than the ending number.
- Input: nums =
-
Example 3:
- Input: nums =
[1, 2, 12, 2, 5, 11, 13] - Expected Output:
4 - Justification: The largest semi-decreasing subarray is [12, 2, 5, 11].
- Input: nums =
Solution
To solve this problem, we adopt a straightforward yet effective approach by examining all possible contiguous subarrays within the given array to identify those that meet the specific criterion of being semi-decreasing. This means we look for segments where the starting element is strictly greater than the ending element, without imposing restrictions on the sequence's behavior between these two points. Through meticulous iteration, starting from each element and comparing it with subsequent elements, we ensure no potential solution is overlooked.
This exhaustive method, while simple, leverages the power of brute force to methodically parse through the array, ensuring that the maximum length of any such semi-decreasing subarray is captured accurately. By evaluating each segment's starting and ending points against our criteria, we pinpoint the longest segment that fulfills the condition, thus arriving at the solution.
Step-by-step Algorithm
-
Initialize Variables:
- Start with a variable
maxLengthset to 0, which will hold the maximum length of a semi-decreasing subarray found. - Use two nested loops with indices
iandjto iterate through the array, whereistarts from 0 andjstarts fromi + 1.
- Start with a variable
-
Iterate Through the Array:
- The outer loop runs through each element of the array, treating each element as a potential starting point of a semi-decreasing subarray.
- The inner loop runs from the next element after
ito the end of the array, considering each as a potential end of a semi-decreasing subarray starting ati.
-
Check for Semi-Decreasing Subarray:
- Within the inner loop, check if the element at the start of the subarray (index
i) is greater than the element at the current end of the subarray (indexj). This checks the condition for a subarray being semi-decreasing.
- Within the inner loop, check if the element at the start of the subarray (index
-
Update Maximum Length:
- If the condition in step 3 is true, calculate the length of the current subarray (
j - i + 1) and compare it withmaxLength. - Update
maxLengthif the current subarray's length is greater.
- If the condition in step 3 is true, calculate the length of the current subarray (
-
Return Result:
- After the loops complete, return the value of
maxLength, which now contains the length of the longest semi-decreasing subarray found.
- After the loops complete, return the value of
Algorithm Walkthrough
Let's consider the Input: nums = [1, 2, 12, 2, 5, 11, 13].
-
Initialization:
maxLengthis initialized to 0. This variable will store the length of the longest semi-decreasing subarray found.
-
Iterate with
i=0(nums[i]=1):- Iterate
jfrom1to the end of the array. Sincenums[0]is less than all other elements (due to the increasing order at the beginning), nojwill satisfynums[i] > nums[j]for this round.
- Iterate
-
Iterate with
i=1(nums[i]=2):- Similarly,
nums[1]is less than all elements to its right, so again, nojwill satisfy the condition for thisi.
- Similarly,
-
Iterate with
i=2(nums[i]=12):- For
j=3(nums[j]=2): The condition is satisfied. CalculatetempLength = 2. UpdatemaxLength = 2.. - For
j=4(nums[j]=5): The condition is satisfied. CalculatetempLength = 3. UpdatemaxLength = 3.. - For
j=5(nums[j]=11): The condition is satisfied. CalculatetempLength = 4, updatemaxLengthto 4. - For
j=6(nums[j]=13): The condition is not satisfied. No update tomaxLength.
- For
-
Iterate with
i=3(nums[i]=2):- All subsequent
jvalues for thisido not satisfynums[i] > nums[j]becausenums[i]is one of the smallest.
- All subsequent
-
Iterate with
i=4(nums[i]=5):- The process is similar to previous steps, with no updates to
maxLengthdue to the condition not being met or finding shorter lengths than currently stored inmaxLength.
- The process is similar to previous steps, with no updates to
-
Iterate with
i=5(nums[i]=11):- For
j=6(nums[j]=13): The condition is not satisfied. No update tomaxLength.
- For
-
Conclusion:
- The iteration ends with
maxLength = 4, representing the longest semi-decreasing subarray[12, 2, 5, 11].
- The iteration ends with
Code
public class Solution {
public int findMaxLength(int[] nums) {
// Initialize variables to track the maximum length
int maxLength = 0, tempLength, n = nums.length;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// Check if the current segment meets the criteria
if (nums[i] > nums[j]) {
tempLength = j - i + 1;
maxLength = Math.max(maxLength, tempLength);
}
}
}
return maxLength;
}
public static void main(String[] args) {
Solution sol = new Solution();
// Example 1
System.out.println(sol.findMaxLength(new int[] { 8, 4, 5, 3, 2 }));
// Example 2
System.out.println(sol.findMaxLength(new int[] { 1, 2, 3, 4, 5 }));
// Example 3
System.out.println(sol.findMaxLength(new int[] { 1, 2, 12, 2, 5, 11, 13 }));
}
}
Complexity Analysis
Time Complexity:
The nested loops iterate over each pair of elements in the array to check every possible subarray. Therefore, the time complexity is quadratic in the number of elements, n, in the input array.
Space Complexity:
Only a constant amount of extra space is used (variables for storing indices, lengths, and the maximum length found), so the space complexity is constant.
Optimized Solution
To solve this problem, we use a monotonic stack to efficiently find the maximum length of a semi-decreasing subarray. The idea is to track indices of elements in increasing order in the stack. Then, by traversing the array from right to left, we check where each element forms a semi-decreasing subarray. If an element is smaller than the element at the top of the stack, it means we have found a decreasing pattern, and we compute the subarray length.
This approach ensures that each index is pushed and popped at most once, leading to an
Step-by-Step Algorithm
-
Initialize Required Variables:
- Create an empty monotonic stack to store indices.
- Store the length of the array in a variable
n. - Initialize
maxLength = 0to keep track of the maximum subarray length.
-
First Pass (Building the Stack - Left to Right):
- Iterate through the array from index
0ton - 1. - For each element:
- If the stack is empty or the current element is greater than the element at the top index, push its index onto the stack.
- This ensures the stack maintains indices in increasing order, which helps in identifying valid decreasing subarrays later.
- Iterate through the array from index
-
Second Pass (Finding Maximum Subarray - Right to Left):
- Traverse the array from right to left (index
n - 1to0). - For each element:
- While the stack is not empty and the element at the top of the stack is greater than the current element, perform the following:
- Compute the subarray length as (i - stack.peek() + 1).
- Update
maxLengthif the computed subarray length is greater than its current value. - Pop the top element from the stack.
- This ensures that we correctly determine the longest subarray where the first element is greater than the last, creating a valid semi-decreasing sequence.
- While the stack is not empty and the element at the top of the stack is greater than the current element, perform the following:
- Traverse the array from right to left (index
-
Return the Final Result:
- After completing both passes, return the maximum subarray length stored in
maxLength.
- After completing both passes, return the maximum subarray length stored in
Algorithm Walkthrough
Input: [1, 2, 12, 2, 5, 11, 13]
1. Initialization
- Input Array:
[1, 2, 12, 2, 5, 11, 13] - Stack:
[](empty initially) - maxLength:
0 - n:
7
2. First Pass – Building the Stack (Left to Right)
- Iteration 1 (
i = 0):nums[0] = 1- Stack is empty → Push index 0.
- Stack becomes:
[0]
- Iteration 2 (
i = 1):nums[1] = 2- Top index is
0withnums[0] = 1which is less than2→ Push index 1. - Stack becomes:
[0, 1]
- Iteration 3 (
i = 2):nums[2] = 12- Top index is
1withnums[1] = 2(2 < 12) → Push index 2. - Stack becomes:
[0, 1, 2]
- Iteration 4 (
i = 3):nums[3] = 2- Top index is
2withnums[2] = 12(12 > 2) → Do not push. - Stack remains:
[0, 1, 2]
- Iteration 5 (
i = 4):nums[4] = 5- Top index is still
2withnums[2] = 12(12 > 5) → Do not push. - Stack remains:
[0, 1, 2]
- Iteration 6 (
i = 5):nums[5] = 11- Top index is still
2withnums[2] = 12(12 > 11) → Do not push. - Stack remains:
[0, 1, 2]
- Iteration 7 (
i = 6):nums[6] = 13- Top index is
2withnums[2] = 12(12 < 13) → Push index 6. - Stack becomes:
[0, 1, 2, 6]
3. Second Pass – Calculating Maximum Subarray Length (Right to Left)
We now traverse from right to left. For each index i, we repeatedly check if the element at the top of the stack is greater than nums[i]. If so, we compute the subarray length using that index and then pop it off.
- Iteration 1 (
i = 6):nums[6] = 13- Stack Top: Index
6→nums[6] = 13is not greater thannums[6](they are equal). - No pop occurs.
- Stack remains:
[0, 1, 2, 6]
- Iteration 2 (
i = 5):nums[5] = 11- Stack Top: Index
6→nums[6] = 13is greater than11.- Calculate subarray length:
- Use
i(5) and stack top (6): - Length =
i - stack.peek() + 1 = 5 - 6 + 1 = 0
- Use
- Update:
maxLengthremains0. - Pop index 6.
- Calculate subarray length:
- Stack becomes:
[0, 1, 2] - While Loop Check Again:
- Now, top is index
2→nums[2] = 12is greater than11. - Calculate subarray length:
- Length =
5 - 2 + 1 = 4
- Length =
- Update:
maxLengthbecomes4. - Pop index 2.
- Now, top is index
- Stack becomes:
[0, 1] - While Loop Ends:
- Now, top is index
1withnums[1] = 2which is not greater than11.
- Now, top is index
- Iteration 3 (
i = 4):nums[4] = 5- Stack Top: Index
1→nums[1] = 2(2 is not greater than 5). - No pop occurs.
- Stack remains:
[0, 1]
- Iteration 4 (
i = 3):nums[3] = 2- Stack Top: Index
1→nums[1] = 2is not greater than2(equal). - No pop occurs.
- Stack remains:
[0, 1]
- Iteration 5 (
i = 2):nums[2] = 12- Stack Top: Index
1→nums[1] = 2is not greater than12. - No pop occurs.
- Stack remains:
[0, 1]
- Iteration 6 (
i = 1):nums[1] = 2- Stack Top: Index
1itself, so nothing to compare. - No pop occurs.
- Stack remains:
[0, 1]
- Iteration 7 (
i = 0):nums[0] = 1- Stack Top: Index
1→nums[1] = 2is greater than1.- Calculate subarray length:
- Length =
0 - 1 + 1 = 0
- Length =
- maxLength remains:
4. - Pop index 1.
- Calculate subarray length:
- Stack becomes:
[0] - While Loop Check Again:
- Now, top is index
0→nums[0] = 1is not greater than1.
- Now, top is index
- While Loop Ends.
- Stack remains:
[0]
4. Final Output
- Final maxLength:
4 - Thus, the maximum length of a semi-decreasing subarray for the array
[1, 2, 12, 2, 5, 11, 13]is4.
Code
import java.util.Stack;
class Solution {
public int findMaxLength(int[] nums) {
Stack<Integer> stack = new Stack<>(); // Monotonic stack to track indices
int n = nums.length;
// First pass: Build a stack with indices of elements in increasing order
for (int i = 0; i < n; i++) {
// Push index onto stack if it's empty or the current element is greater than the top element
if (stack.isEmpty() || nums[stack.peek()] < nums[i]) {
stack.push(i);
}
}
int maxLength = 0;
// Second pass: Traverse the array from the end to calculate the max subarray length
for (int i = n - 1; i >= 0; i--) {
// If the top of the stack is greater than the current element, calculate length
while (!stack.isEmpty() && nums[stack.peek()] > nums[i]) {
maxLength = Math.max(maxLength, i - stack.peek() + 1);
stack.pop(); // Remove the top index as it's processed
}
}
return maxLength;
}
public static void main(String[] args) {
Solution sol = new Solution();
// Example 1
System.out.println(sol.findMaxLength(new int[] { 8, 4, 5, 3, 2 })); // Expected output: 5
// Example 2
System.out.println(sol.findMaxLength(new int[] { 1, 2, 3, 4, 5 })); // Expected output: 0
// Example 3
System.out.println(sol.findMaxLength(new int[] { 1, 2, 12, 2, 5, 11, 13 })); // Expected output: 4
}
}
Complexity Analysis
Time Complexity Analysis
-
First Pass (Building the Stack) →
- We iterate over the array from left to right (
i = 0ton-1). - Each element is pushed onto the stack at most once.
- Total operations:
.
- We iterate over the array from left to right (
-
Second Pass (Finding Maximum Subarray Length) →
- We iterate over the array from right to left (
i = n-1to0). - Each element is popped from the stack at most once.
- Total operations:
.
- We iterate over the array from right to left (
Since both passes run in
Space Complexity Analysis
- Stack Storage →
- In the worst case, the stack may store all
nindices (e.g., when elements are strictly increasing). - Space used by the stack:
.
- In the worst case, the stack may store all
- Other Variables →
- The algorithm uses a few integer variables (
maxLength,n, loop counters), which require constant space.
- The algorithm uses a few integer variables (
Thus, the overall space complexity is
🤖 Don't fully get this? Learn it with Claude
Stuck on Maximum Length of Semi-Decreasing Subarrays? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Maximum Length of Semi-Decreasing Subarrays** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Maximum Length of Semi-Decreasing Subarrays** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Maximum Length of Semi-Decreasing Subarrays**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Maximum Length of Semi-Decreasing Subarrays**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.