Facebook Pixel

2393. Count Strictly Increasing Subarrays 🔒

Problem Description

You are given an array nums consisting of positive integers.

Your task is to count the total number of subarrays that are in strictly increasing order.

A subarray is a contiguous part of an array, meaning the elements must be consecutive in the original array. A subarray is strictly increasing if each element is greater than the previous element (for subarrays with more than one element).

For example, if nums = [1, 3, 2, 4]:

  • The strictly increasing subarrays are: [1], [3], [2], [4], [1, 3], [2, 4]
  • Total count = 6

Note that single elements are considered strictly increasing subarrays by default.

The solution works by tracking how many strictly increasing subarrays end at each position. For each element, if it's greater than the previous element, we can extend all strictly increasing subarrays ending at the previous position by including the current element, plus the subarray containing just the current element itself. The variable cnt keeps track of how many strictly increasing subarrays end at the current position, and we accumulate these counts to get the final answer.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is to think about how strictly increasing subarrays are formed and how they relate to each other at different positions in the array.

Consider what happens at each position in the array. Every element by itself forms a valid strictly increasing subarray of length 1. But when we look at an element in relation to its previous element, two scenarios emerge:

  1. If the current element is greater than the previous element: All the strictly increasing subarrays that ended at the previous position can be extended to include the current element. For instance, if we had 3 strictly increasing subarrays ending at position i-1, we can extend all of them to position i, giving us 3 extended subarrays plus the single-element subarray at position i.

  2. If the current element is not greater than the previous element: The strictly increasing sequence is broken. We can't extend any previous subarrays, so we start fresh with only the single-element subarray at the current position.

This leads to a counting pattern. If we maintain a counter cnt that tracks how many strictly increasing subarrays end at the current position:

  • When we can extend (current > previous): cnt increases by 1 (we add the extended subarrays plus the single element)
  • When we can't extend: cnt resets to 1 (only the single element subarray)

By accumulating these counts as we traverse the array, we get the total number of strictly increasing subarrays. This works because we're essentially counting each valid subarray exactly once - at the position where it ends.

Learn more about Math and Dynamic Programming patterns.

Solution Approach

The implementation follows a linear scan approach with a running counter to track strictly increasing subarrays.

Algorithm Steps:

  1. Initialize variables:

    • ans to store the total count of strictly increasing subarrays, initialized to 1 (for the first element)
    • cnt to track the number of strictly increasing subarrays ending at the current position, initialized to 1
  2. Traverse the array using consecutive pairs: Using pairwise(nums), we iterate through consecutive elements (x, y) where x is the previous element and y is the current element.

  3. Update the counter based on comparison:

    • If x < y (strictly increasing): increment cnt by 1. This means we can extend all cnt subarrays that ended at x to include y, plus the single-element subarray [y]
    • Otherwise: reset cnt to 1, as we can only have the single-element subarray [y] ending at this position
  4. Accumulate the count: Add cnt to ans after each iteration. This adds the count of all strictly increasing subarrays ending at the current position to our total.

  5. Return the result: After traversing all pairs, ans contains the total count of strictly increasing subarrays.

Example walkthrough with nums = [1, 3, 2, 4]:

  • Start: ans = 1, cnt = 1 (for element 1)
  • Pair (1, 3): 1 < 3, so cnt = 2, ans = 1 + 2 = 3
  • Pair (3, 2): 3 ≮ 2, so cnt = 1, ans = 3 + 1 = 4
  • Pair (2, 4): 2 < 4, so cnt = 2, ans = 4 + 2 = 6
  • Result: 6 strictly increasing subarrays

Time Complexity: O(n) where n is the length of the array, as we traverse the array once.

Space Complexity: O(1) as we only use a constant amount of extra space for variables.

Ready to land your dream job?

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

Start Evaluator

Example Walkthrough

Let's walk through the solution with nums = [2, 5, 3, 6, 7].

We'll track cnt (number of strictly increasing subarrays ending at current position) and ans (total count).

Initial state:

  • ans = 1 (for the first element [2])
  • cnt = 1 (one subarray ending at position 0)

Step 1: Compare elements (2, 5)

  • Since 2 < 5, we can extend the subarray ending at 2
  • cnt = cnt + 1 = 2 (subarrays ending at 5: [5] and [2,5])
  • ans = ans + cnt = 1 + 2 = 3
  • Running subarrays found: [2], [5], [2,5]

Step 2: Compare elements (5, 3)

  • Since 5 ≮ 3, we cannot extend any subarray
  • cnt = 1 (only [3] ends at this position)
  • ans = ans + cnt = 3 + 1 = 4
  • New subarray found: [3]

Step 3: Compare elements (3, 6)

  • Since 3 < 6, we can extend the subarray ending at 3
  • cnt = cnt + 1 = 2 (subarrays ending at 6: [6] and [3,6])
  • ans = ans + cnt = 4 + 2 = 6
  • New subarrays found: [6], [3,6]

Step 4: Compare elements (6, 7)

  • Since 6 < 7, we can extend the subarrays ending at 6
  • cnt = cnt + 1 = 3 (subarrays ending at 7: [7], [6,7], and [3,6,7])
  • ans = ans + cnt = 6 + 3 = 9
  • New subarrays found: [7], [6,7], [3,6,7]

Final Result: 9

All strictly increasing subarrays: [2], [5], [2,5], [3], [6], [3,6], [7], [6,7], [3,6,7]

The key insight: when elements are strictly increasing, cnt grows because we extend all previous subarrays plus add the single element. When the sequence breaks, cnt resets to 1, starting fresh.

Solution Implementation

1class Solution:
2    def countSubarrays(self, nums: List[int]) -> int:
3        """
4        Count the number of subarrays where elements are in strictly increasing order.
5      
6        Args:
7            nums: List of integers
8          
9        Returns:
10            Total count of strictly increasing subarrays
11        """
12        # Initialize result and current subarray length
13        total_count = 1  # Every single element counts as a subarray
14        current_length = 1  # Length of current increasing subarray ending at current position
15      
16        # Iterate through consecutive pairs of elements
17        for i in range(1, len(nums)):
18            # Check if current element is greater than previous element
19            if nums[i - 1] < nums[i]:
20                # Extend the current increasing subarray
21                current_length += 1
22            else:
23                # Reset to new subarray starting at current element
24                current_length = 1
25          
26            # Add count of all subarrays ending at current position
27            # This includes all increasing subarrays of different lengths ending here
28            total_count += current_length
29      
30        return total_count
31
1class Solution {
2    public long countSubarrays(int[] nums) {
3        // Total count of valid subarrays
4        long totalCount = 1;
5      
6        // Length of current strictly increasing subarray ending at current position
7        long currentLength = 1;
8      
9        // Iterate through the array starting from the second element
10        for (int i = 1; i < nums.length; i++) {
11            // Check if current element is greater than previous element
12            if (nums[i - 1] < nums[i]) {
13                // Extend the current strictly increasing subarray
14                currentLength++;
15            } else {
16                // Reset to new subarray starting at current position
17                currentLength = 1;
18            }
19          
20            // Add all subarrays ending at current position to total count
21            // currentLength represents the number of valid subarrays ending at index i
22            totalCount += currentLength;
23        }
24      
25        return totalCount;
26    }
27}
28
1class Solution {
2public:
3    long long countSubarrays(vector<int>& nums) {
4        // Total count of valid subarrays
5        long long totalCount = 1;
6      
7        // Length of current strictly increasing subarray ending at current position
8        long long currentLength = 1;
9      
10        // Iterate through the array starting from the second element
11        for (int i = 1; i < nums.size(); ++i) {
12            // Check if current element is greater than previous element
13            if (nums[i - 1] < nums[i]) {
14                // Extend the current strictly increasing subarray
15                ++currentLength;
16            } else {
17                // Reset to new subarray starting at current element
18                currentLength = 1;
19            }
20          
21            // Add all subarrays ending at current position to total count
22            // currentLength represents the number of valid subarrays ending at index i
23            totalCount += currentLength;
24        }
25      
26        return totalCount;
27    }
28};
29
1/**
2 * Counts the total number of subarrays where elements are in strictly increasing order.
3 * @param nums - The input array of numbers
4 * @returns The total count of strictly increasing subarrays
5 */
6function countSubarrays(nums: number[]): number {
7    // Initialize the total count and current subarray length
8    let totalCount: number = 1;  // At least one subarray (first element itself)
9    let currentLength: number = 1;  // Length of current increasing subarray
10  
11    // Iterate through the array starting from the second element
12    for (let i: number = 1; i < nums.length; i++) {
13        // Check if current element is greater than previous element
14        if (nums[i - 1] < nums[i]) {
15            // Extend the current increasing subarray
16            currentLength++;
17        } else {
18            // Reset the current subarray length as the increasing pattern breaks
19            currentLength = 1;
20        }
21      
22        // Add the number of subarrays ending at current position
23        // This equals the length of the current increasing subarray
24        totalCount += currentLength;
25    }
26  
27    return totalCount;
28}
29

Time and Space Complexity

The time complexity is O(n), where n is the length of the array nums. The algorithm uses pairwise(nums) to iterate through consecutive pairs of elements in the array, which results in n-1 iterations. Each iteration performs constant time operations: comparing two elements (x < y), updating the counter cnt, and adding to ans. Since we perform a constant amount of work for each of the n-1 pairs, the overall time complexity is linear.

The space complexity is O(1). The algorithm only uses a fixed amount of extra space regardless of the input size. The variables ans, cnt, x, and y are the only additional memory used, and their space requirements don't scale with the input size. The pairwise iterator doesn't create a new data structure but rather generates pairs on-the-fly, maintaining constant space usage.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Misunderstanding what current_length represents

Pitfall: Many developers mistakenly think current_length represents just the length of the longest increasing subarray ending at the current position, missing that it actually represents the count of all strictly increasing subarrays ending at that position.

Why this happens: The variable name current_length can be misleading. When we have an increasing sequence like [1, 3, 5], at position 2 (element 5), current_length = 3 doesn't just mean the longest subarray has length 3. It means there are 3 strictly increasing subarrays ending at position 2: [5], [3, 5], and [1, 3, 5].

Solution: Use a more descriptive variable name like subarrays_ending_here or add clear comments:

def countSubarrays(self, nums: List[int]) -> int:
    total_count = 1
    # This represents COUNT of strictly increasing subarrays ending at current position
    # NOT the length of the longest subarray
    subarrays_ending_here = 1
  
    for i in range(1, len(nums)):
        if nums[i - 1] < nums[i]:
            # We can extend all previous subarrays + add single element subarray
            subarrays_ending_here += 1
        else:
            # Only the single element subarray is valid
            subarrays_ending_here = 1
      
        total_count += subarrays_ending_here
  
    return total_count

2. Forgetting to handle single-element subarrays

Pitfall: Implementing logic that only counts subarrays with 2+ elements, forgetting that single elements are valid strictly increasing subarrays by definition.

Incorrect approach:

def countSubarrays(self, nums: List[int]) -> int:
    total_count = 0  # Wrong: missing initial single element
    current_length = 0  # Wrong: should start at 1
  
    for i in range(1, len(nums)):
        if nums[i - 1] < nums[i]:
            current_length += 1
            total_count += current_length  # Misses single-element subarrays
        else:
            current_length = 0  # Wrong: should be 1
  
    return total_count

Solution: Always initialize counters to 1 to account for single-element subarrays, and reset to 1 (not 0) when the sequence breaks.

3. Off-by-one errors with array boundaries

Pitfall: Starting the loop at index 0 instead of 1, causing index out of bounds when accessing nums[i-1].

Incorrect approach:

def countSubarrays(self, nums: List[int]) -> int:
    total_count = 0
    current_length = 1
  
    for i in range(len(nums)):  # Wrong: should start at 1
        if nums[i - 1] < nums[i]:  # Error when i = 0
            current_length += 1
        else:
            current_length = 1
        total_count += current_length
  
    return total_count

Solution: Start the loop at index 1 and initialize total_count to 1 to account for the first element, or add boundary checks.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which type of traversal does breadth first search do?


Recommended Readings

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

Load More