Given an array of integers arr, find the sum of min(b), where b ranges over every (contiguous) subarray of arr. Since the answer may be large, return the answer modulo 109 + 7.
Example 1:
Input: arr = [3,1,2,4] Output: 17 Explanation: Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4]. Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1. Sum is 17.
Example 2:
Input: arr = [11,81,94,43,3] Output: 444
Constraints:
1 <= arr.length <= 3 * 1041 <= arr[i] <= 3 * 104When 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 approach to finding the sum of subarray minimums involves looking at every possible group of numbers within the larger set. For each of these groups, we'll find the smallest number and then add it to our running total. Finally, after checking every group, we'll have our answer.
Here's how the algorithm would work step-by-step:
def sum_subarray_minimums_brute_force(array):
total_sum = 0
array_length = len(array)
# Iterate through all possible starting positions of subarrays
for start_index in range(array_length):
# Iterate through all possible ending positions of subarrays
for end_index in range(start_index, array_length):
minimum_value = array[start_index]
# Find the minimum element within the current subarray
for current_index in range(start_index, end_index + 1):
if array[current_index] < minimum_value:
minimum_value = array[current_index]
# Add the minimum of the subarray to the total sum
total_sum += minimum_value
return total_sumThe efficient way to find the sum of the minimum values of all subarrays avoids recalculating the minimum for each subarray. It cleverly uses a 'stack' to keep track of relevant elements and their contribution to the final sum, significantly reducing redundant work.
Here's how the algorithm would work step-by-step:
def sum_subarray_minimums(arr):
length_of_array = len(arr)
modulo = 10**9 + 7
stack = []
sum_of_minimums = 0
# Find previous less element for each element.
previous_less_element = [0] * length_of_array
for i in range(length_of_array):
while stack and arr[stack[-1]] > arr[i]:
stack.pop()
previous_less_element[i] = stack[-1] if stack else -1
stack.append(i)
stack = []
# Find next less element for each element.
next_less_element = [0] * length_of_array
for i in range(length_of_array - 1, -1, -1):
while stack and arr[stack[-1]] >= arr[i]:
stack.pop()
next_less_element[i] = stack[-1] if stack else length_of_array
stack.append(i)
# Calculate the contribution of each element as minimum.
for i in range(length_of_array):
left_distance = i - previous_less_element[i]
# Distance to the next smaller element.
right_distance = next_less_element[i] - i
sum_of_minimums += arr[i] * left_distance * right_distance
sum_of_minimums %= modulo
return sum_of_minimums| Case | How to Handle |
|---|---|
| Empty input array | Return 0 as there are no subarrays. |
| Array with a single element | Return the element itself, as it's the only subarray and its minimum. |
| Array with all identical elements | The minimum of each subarray is the same element, so calculate number of subarrays correctly (n*(n+1))/2 * element and return modulo. |
| Array with very large numbers that could lead to integer overflow when summing | Apply the modulo operation (10^9 + 7) after each addition to prevent integer overflow. |
| Array containing negative numbers | The algorithm should handle negative numbers correctly since it compares values to find the minimum. |
| Array with a mix of large positive and large negative numbers | Ensure the modulo operation handles negative results correctly (e.g., by adding the modulo value if the result is negative). |
| Large input array size (performance) | Optimized algorithms like using a stack to determine the left and right boundaries for each element being the minimum within a range are needed for efficiency. |
| Array with zeros | Zeros should be handled correctly as they could be the minimum in several subarrays. |