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 - 2 = 1 [1,2,3], range = 3 - 1 = 2 So the sum of all ranges is 0 + 0 + 0 + 1 + 1 + 2 = 4.
Example 2:
Input: nums = [1,3,3] Output: 4 Explanation: The 6 subarrays of nums are the following: [1], range = largest - smallest = 1 - 1 = 0 [3], range = 3 - 3 = 0 [3], range = 3 - 3 = 0 [1,3], range = 3 - 1 = 2 [3,3], range = 3 - 3 = 0 [1,3,3], range = 3 - 1 = 2 So the sum of all ranges is 0 + 0 + 0 + 2 + 0 + 2 = 4.
Example 3:
Input: nums = [4,-2,-3,4,1] Output: 59 Explanation: The sum of all subarray ranges of nums is 59.
Constraints:
1 <= nums.length <= 1000
-109 <= nums[i] <= 109
Follow-up: Could you find a solution with O(n)
time complexity?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force way to find the sum of subarray ranges means we'll look at every possible group of numbers in our list. For each group, we'll find the biggest and smallest numbers, then subtract the smallest from the biggest. Finally, we'll add up all those differences to get our final answer.
Here's how the algorithm would work step-by-step:
def sub_array_ranges_brute_force(numbers):
result = 0
# Iterate through all possible starting indices
for start_index in range(len(numbers)):
# Iterate through all possible ending indices
for end_index in range(start_index, len(numbers)):
# Initialize min/max with the starting element.
minimum_number = numbers[start_index]
maximum_number = numbers[start_index]
# Iterate through current subarray
for current_index in range(start_index, end_index + 1):
# Find the min and max values in the subarray
minimum_number = min(minimum_number, numbers[current_index])
maximum_number = max(maximum_number, numbers[current_index])
# Accumulate difference to final result
result += maximum_number - minimum_number
return result
Instead of checking the range of every possible group, the key idea is to find how many times each individual number acts as the smallest and largest within some group. Then we use this information to directly calculate the sum of ranges, avoiding redundant calculations. This dramatically improves efficiency.
Here's how the algorithm would work step-by-step:
def sub_array_ranges(group):
group_length = len(group)
max_sum = 0
min_sum = 0
# Calculate contribution of each num as max.
for i in range(group_length):
left_boundary = 1
right_boundary = 1
while i - left_boundary >= 0 and group[i - left_boundary] <= group[i]:
left_boundary += 1
while i + right_boundary < group_length and group[i + right_boundary] < group[i]:
right_boundary += 1
# Accumulate how each number contributes as largest.
max_sum += group[i] * left_boundary * right_boundary
# Calculate contribution of each num as min.
for i in range(group_length):
left_boundary = 1
right_boundary = 1
while i - left_boundary >= 0 and group[i - left_boundary] >= group[i]:
left_boundary += 1
while i + right_boundary < group_length and group[i + right_boundary] > group[i]:
right_boundary += 1
# Accumulate how each number contributes as smallest.
min_sum += group[i] * left_boundary * right_boundary
# Difference between max and min contributions gives the result.
return max_sum - min_sum
Case | How to Handle |
---|---|
Null or empty input array | Return 0 immediately as there are no subarrays to calculate ranges from. |
Array with a single element | Return 0 as a single-element subarray has a range of 0 (element - element). |
Array with all identical values | The sum of subarray ranges will be 0 because each subarray's minimum and maximum are the same. |
Array with negative numbers | The algorithm should correctly handle negative numbers when calculating the min and max of each subarray. |
Array with large numbers that might lead to integer overflow when calculating the sum of ranges. | Use a 64-bit integer type (long in Java/C++) to store the sum of ranges to prevent overflow. |
Very large input array (performance) | A brute-force O(n^2) solution might be too slow; consider using stack-based or segment tree approaches for O(n) or O(n log n) performance. |
Array containing Integer.MAX_VALUE and Integer.MIN_VALUE | Ensure calculations handle the boundaries correctly when computing min/max and their differences. |
The array has many subarrays with the same range | The algorithm should still process each subarray individually to calculate the sum, regardless of repeated range values. |