Facebook Pixel

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:

  1. 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.
  2. 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.

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:

  1. Initial Setup:

    • Initialize ans to store the maximum length found, and t to store the current subarray length, both starting at 1.
  2. 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 increment t.
      • If x <= nums[i], reset t to 1 to start a new potential increasing subarray.
    • Update ans with the maximum of its current value and t.
for i, x in enumerate(nums[1:]):
    if nums[i] < x:
        t += 1
        ans = max(ans, t)
    else:
        t = 1
  1. Reset for Second Pass:

    • Set t back to 1 to compute decreasing subarray lengths anew.
  2. Second Pass: Strictly Decreasing Subarray:

    • Again, traverse nums, comparing each element x with the one before:
      • If x < nums[i], increment t indicating the array is decreasing.
      • Otherwise, reset t to 1.
    • Update ans similarly with any longer decreasing subarray discovered.
t = 1
for i, x in enumerate(nums[1:]):
    if nums[i] > x:
        t += 1
        ans = max(ans, t)
    else:
        t = 1
  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.

Ready to land your dream job?

Unlock your dream job with a 2-minute evaluator for a personalized learning plan!

Start Evaluator

Example 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).
  1. Index 1: Compare 8 with 3.

    • Since 8 > 3, the sequence is increasing. Increment t to 2.
    • Update ans to the maximum of ans and t, which is now 2.
  2. Index 2: Compare 5 with 8.

    • Since 5 <= 8, reset t to 1.
  3. Index 3: Compare 7 with 5.

    • Since 7 > 5, increment t to 2.
    • ans remains 2, as it is still the maximum.
  4. Index 4: Compare 6 with 7.

    • Since 6 <= 7, reset t to 1.
  5. Index 5: Compare 2 with 6.

    • Since 2 <= 6, t remains 1.
  6. Index 6: Compare 4 with 2.

    • Since 4 > 2, increment t to 2.
  7. Index 7: Compare 1 with 4.

    • Since 1 <= 4, reset t to 1.

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.
  1. Index 1: Compare 8 with 3.

    • Since 8 <= 3, t remains 1.
  2. Index 2: Compare 5 with 8.

    • Since 5 < 8, increment t to 2.
    • Update ans to the maximum of ans and t, which is now 2.
  3. Index 3: Compare 7 with 5.

    • Since 7 >= 5, reset t to 1.
  4. Index 4: Compare 6 with 7.

    • Since 6 < 7, increment t to 2.
    • ans remains 2.
  5. Index 5: Compare 2 with 6.

    • Since 2 < 6, increment t to 3.
    • Update ans to 3, which is now the maximum.
  6. Index 6: Compare 4 with 2.

    • Since 4 >= 2, reset t to 1.
  7. Index 7: Compare 1 with 4.

    • Since 1 < 4, increment t to 2.

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.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

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

Want a Structured Path to Master System Design Too? Don’t Miss This!


Load More