Sum of Subarray Ranges - Complete Solution Guide
Sum of Subarray Ranges is LeetCode problem 2104, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
You are given an integer array nums . The range of a subarray of nums is the difference between the largest and smallest element in the subarray. Return the sum of all subarray ranges of nums . A subarray is a contiguous non-empty sequence of elements within an array. Example 1: Input: nums = [1,2,3] Output: 4 Explanation: The 6 subarrays of nums are the following: [1], range = largest - smallest = 1 - 1 = 0 [2], range = 2 - 2 = 0 [3], range = 3 - 3 = 0 [1,2], range = 2 - 1 = 1 [2,3], range = 3
Detailed Explanation
The problem asks us to calculate the sum of ranges of all possible non-empty subarrays of a given integer array `nums`. The range of a subarray is defined as the difference between its largest and smallest elements. For example, if `nums = [1, 2, 3]`, we need to consider all subarrays: `[1]`, `[2]`, `[3]`, `[1, 2]`, `[2, 3]`, and `[1, 2, 3]`. Then, for each subarray, calculate its range (max - min) and sum up all those ranges to get the final result.
Solution Approach
The solution employs a monotonic stack approach to efficiently calculate the sum of maximums and sum of minimums of all subarrays. It first calculates the contribution of each element as the maximum element in various subarrays and sums them up. Then, it does the same for the minimum element. Finally, it subtracts the total sum of minimums from the total sum of maximums to get the final answer.
Step-by-Step Algorithm
- Step 1: **Find Next Greater Element (NG) and Previous Greater or Equal Element (PGE):** For each element `nums[i]`, find the index of the next greater element to its right (NG[i]) and the index of the previous greater or equal element to its left (PGE[i]). This is done using a monotonic decreasing stack.
- Step 2: **Calculate Sum of Maximums:** Iterate through the array. For each element `nums[i]`, calculate the number of subarrays where it's the maximum. This number is `(i - PGE[i]) * (NG[i] - i)`. Multiply this by `nums[i]` and add it to `sum_max`.
- Step 3: **Find Next Less Element (NL) and Previous Less or Equal Element (PLE):** Similar to Step 1, find the index of the next less element to the right (NL[i]) and the index of the previous less or equal element to the left (PLE[i]). This is done using a monotonic increasing stack.
- Step 4: **Calculate Sum of Minimums:** Iterate through the array. For each element `nums[i]`, calculate the number of subarrays where it's the minimum. This number is `(i - PLE[i]) * (NL[i] - i)`. Multiply this by `nums[i]` and add it to `sum_min`.
- Step 5: **Calculate the Result:** Return `sum_max - sum_min`.
Key Insights
- Insight 1: Calculating the range of each subarray individually by iterating through all possible subarrays would result in O(n^2) subarrays, and finding the max and min of each would be O(n) for a total of O(n^3) complexity, which is not efficient enough.
- Insight 2: Instead of iterating through all subarrays directly, we can iterate through each number in the array and calculate how many subarrays this number is the maximum or minimum element in. Then calculate the total max sum and total min sum separately and subtract to find the result.
- Insight 3: Monotonic stacks are the perfect data structure for finding the next greater/less and previous greater/less elements efficiently, which are used to determine the number of subarrays where each element is the maximum or minimum.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(n)
Topics
This problem involves: Array, Stack, Monotonic Stack.
Companies
Asked at: J.P. Morgan, TikTok.