githubEdit

11. Sum of Subarray Minimums

βœ… GFG solution to the Sum of Subarray Minimums problem: calculate the sum of minimum elements across all subarrays using monotonic stack technique. πŸš€

The problem can be found at the following link: πŸ”— Question Linkarrow-up-right

🧩 Problem Description

Given an array arr[] of positive integers, find the total sum of the minimum elements of every possible subarray.

A subarray is a contiguous sequence of elements within an array. For each subarray, we identify its minimum element and sum all these minimums together.

Note: It is guaranteed that the total sum will fit within a 32-bit unsigned integer.

πŸ“˜ Examples

Example 1

Input: arr[] = [10, 20]
Output: 40
Explanation: Subarrays are [10], [20], [10, 20]. 
Minimums are 10, 20, 10.
Sum of all these is 10 + 20 + 10 = 40.

Example 2

Input: arr[] = [1, 2, 3, 4]
Output: 20
Explanation: Subarrays are [1], [2], [3], [4], [1, 2], [1, 2, 3], [1, 2, 3, 4], 
[2, 3], [2, 3, 4], [3, 4]. 
Minimums are 1, 2, 3, 4, 1, 1, 1, 2, 2, 3.
Sum of all these is 1 + 2 + 3 + 4 + 1 + 1 + 1 + 2 + 2 + 3 = 20.

πŸ”’ Constraints

  • $1 \le \text{arr.size()} \le 3 \times 10^4$

  • $1 \le \text{arr}[i] \le 10^3$

βœ… My Approach

The optimal approach uses the Monotonic Stack technique to efficiently calculate how many subarrays each element serves as the minimum for:

Two-Boundary Monotonic Stack

  1. Key Insight:

    • For each element arr[i], we need to find how many subarrays have arr[i] as their minimum.

    • This equals: (number of elements we can extend left) Γ— (number of elements we can extend right) Γ— arr[i].

  2. Find Left Boundaries:

    • Use a monotonic increasing stack to find the previous smaller element for each position.

    • left[i] stores the index of the previous smaller element (or -1 if none exists).

    • This tells us how far left we can extend while arr[i] remains the minimum.

  3. Find Right Boundaries:

    • Use another monotonic increasing stack (traverse right to left) to find the next smaller element.

    • right[i] stores the index of the next smaller element (or n if none exists).

    • This tells us how far right we can extend while arr[i] remains the minimum.

  4. Calculate Contribution:

    • For each element at index i:

      • It can be the minimum in (i - left[i]) choices for the left boundary.

      • It can be the minimum in (right[i] - i) choices for the right boundary.

      • Total subarrays where arr[i] is minimum: (i - left[i]) Γ— (right[i] - i).

      • Contribution to sum: arr[i] Γ— (i - left[i]) Γ— (right[i] - i).

  5. Handle Duplicates:

    • Use >= for left boundary and > for right boundary to avoid counting the same subarray twice.

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(n), where n is the size of the array. Each element is pushed and popped from the stack at most once during the left boundary calculation, and once during the right boundary calculation. The final summation loop is also O(n). Therefore, total time is O(n) + O(n) + O(n) = O(n).

  • Expected Auxiliary Space Complexity: O(n), as we use three arrays (left, right, and stack) each of size n. The stack can grow up to n elements in the worst case. Thus, auxiliary space is O(n) + O(n) + O(n) = O(n).

πŸ§‘β€πŸ’» Code (C++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ Dynamic Programming with Right Boundary

πŸ’‘ Algorithm Steps:

  1. Use monotonic stack to find the next smaller element on the right for each position.

  2. Build DP array from right to left where dp[i] represents sum of minimums for all subarrays starting at index i.

  3. For each position, calculate contribution based on whether there's a smaller element to the right.

  4. Sum all DP values to get the final answer.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Two passes through array with stack operations

  • Auxiliary Space: πŸ’Ύ O(n) - Stack, right array, and DP array

βœ… Why This Approach?

  • Clear DP recurrence relation

  • Easy to understand subproblem structure

  • Good for learning DP with monotonic stack

πŸ“Š 3️⃣ Stack with Immediate Contribution

πŸ’‘ Algorithm Steps:

  1. Use a single monotonic stack to process elements from left to right.

  2. When an element is popped, calculate its contribution to all subarrays where it's the minimum.

  3. Track cumulative sum of contributions as we process each element.

  4. Add a sentinel value at the end to flush remaining stack elements.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Single pass with amortized O(1) stack operations

  • Auxiliary Space: πŸ’Ύ O(n) - Only the stack is needed

βœ… Why This Approach?

  • Single-pass processing is elegant

  • Immediate contribution calculation

  • Good for competitive programming

πŸ“Š 4️⃣ Brute Force Enumeration

πŸ’‘ Algorithm Steps:

  1. Enumerate all possible subarrays using two nested loops.

  2. For each subarray, track the minimum element while extending the right boundary.

  3. Add the minimum to the running sum.

  4. Return the total sum modulo 10^9+7.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(nΒ²) - Nested loops with optimized min tracking

  • Auxiliary Space: πŸ’Ύ O(1) - Only constant extra space

βœ… Why This Approach?

  • Simplest to implement and understand

  • No complex data structures needed

  • Good baseline for testing and comparison

⚠️ Note: This approach results in Time Limit Exceeded (TLE) for large inputs near the constraint boundary. (fails ~1110/1120 test cases due to time constraints).

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

🏷️ Two-Boundary Stack

🟒 O(n)

🟑 O(n)

πŸš€ Optimal & intuitive

πŸ’Ύ Requires three arrays

πŸ“Š DP with Right Boundary

🟒 O(n)

🟑 O(n)

πŸ“– Clear DP structure

πŸ”„ More complex recurrence

⚑ Stack Immediate Contrib

🟒 O(n)

🟑 O(n)

⭐ Single pass elegance

🧠 Requires careful index tracking

πŸ” Brute Force

πŸ”΄ O(nΒ²)

🟒 O(1)

🎯 Simple implementation

🐌 Too slow for large inputs

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

πŸ… Optimal performance needed

πŸ₯‡ Two-Boundary Stack

β˜…β˜…β˜…β˜…β˜…

πŸ“– Learning DP patterns

πŸ₯ˆ DP with Right Boundary

β˜…β˜…β˜…β˜…β˜†

πŸ”§ Competitive programming

πŸ₯‰ Stack Immediate Contrib

β˜…β˜…β˜…β˜…β˜…

🎯 Small inputs/Testing

πŸ… Brute Force

β˜…β˜…β˜…β˜†β˜†

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated