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 10^9 + 7
.
For example:
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
Explain and code an efficient algorithm to solve this problem. Consider time and space complexity. Are there any edge cases?
The most straightforward approach is to generate all possible subarrays and find the minimum element in each subarray. Then, sum up all the minimums.
def sum_of_minimums_brute_force(arr):
total_sum = 0
for i in range(len(arr)):
for j in range(i, len(arr)):
sub_array = arr[i:j+1]
total_sum += min(sub_array)
return total_sum
Time Complexity: O(n^3), where n is the length of the array. This is because we have nested loops to generate all subarrays (O(n^2)), and then we find the minimum of each subarray (O(n)).
Space Complexity: O(n), where n is the maximum size of a subarray that has to be held in memory.
A more efficient approach utilizes a stack to find the nearest smaller elements to the left and right of each element in the array. This allows us to determine how many subarrays each element is the minimum for.
Here's how it works:
arr[i]
, find the index left[i]
of the nearest smaller element to the left.arr[i]
, find the index right[i]
of the nearest smaller element to the right.arr[i]
is the minimum is (i - left[i]) * (right[i] - i)
. The sum of minimums is then the sum of arr[i] * (i - left[i]) * (right[i] - i)
for all i.10^9 + 7
, perform modulus operations throughout the calculation.def sum_of_minimums_optimal(arr):
n = len(arr)
left = [0] * n
right = [0] * n
stack = []
# Calculate left boundaries
for i in range(n):
while stack and arr[stack[-1]] > arr[i]:
stack.pop()
left[i] = stack[-1] if stack else -1
stack.append(i)
stack = []
# Calculate right boundaries
for i in range(n - 1, -1, -1):
while stack and arr[stack[-1]] >= arr[i]:
stack.pop()
right[i] = stack[-1] if stack else n
stack.append(i)
MOD = 10**9 + 7
total_sum = 0
for i in range(n):
total_sum = (total_sum + arr[i] * (i - left[i]) * (right[i] - i)) % MOD
return total_sum
Time Complexity: O(n), where n is the length of the array. We iterate through the array three times (once for left, once for right, and once for calculating the sum).
Space Complexity: O(n), for storing the left
and right
arrays and the stack.