Given an array of integers arr of size n, calculate the sum of the minimum value in each (contiguous) subarray of arr. Since the result may be large, return the answer modulo 109 +7.
Input: arr = [3, 1, 2, 5]
Output: 18
Explanation: The minimum of subarrays: [3], [1], [2], [5], [3, 1], [1, 2], [2, 5], [3, 1, 2], [1, 2, 5], [3, 1, 2, 5] are 3, 1, 2, 5, 1, 1, 2, 1, 1, 1 respectively and their sum is 18.
Input: arr = [2, 3, 1]
Output: 10
Explanation: The minimum of subarrays: [2], [3], [1], [2,3], [3,1], [2,3,1] are 2, 3, 1, 2, 1, 1 respectively and their sum is 10.
Input: arr = [11, 81, 94, 43, 3]
The brute force way to solve this problem is by generating all the subarrays and finding the minimum in all of them. All the minimums can be summed up while taking modulus with 109 + 7
to return the result.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to find the sum of the
minimum value in each subarray */
int sumSubarrayMins(vector<int> &arr) {
// Size of array
int n = arr.size();
int mod = 1e9 + 7; // Mod value
// To store the sum
int sum = 0;
// Traverse on the array
for(int i=0; i < n; i++) {
// To store the minimum of subarray
int mini = arr[i];
/* Nested loop to get all
subarrays starting from index i */
for(int j=i; j < n; j++) {
// Update the minimum value
mini = min(mini, arr[j]);
// Update the sum
sum = (sum + mini) % mod;
}
}
// Return the computed sum
return sum;
}
};
int main() {
vector<int> arr = {3, 1, 2, 5};
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to find the sum of the
minimum value in each subarray */
int ans = sol.sumSubarrayMins(arr);
cout << "The sum of minimum value in each subarray is: " << ans;
return 0;
}
import java.util.*;
class Solution {
/* Function to find the sum of the
minimum value in each subarray */
public int sumSubarrayMins(int[] arr) {
// Size of array
int n = arr.length;
int mod = (int)1e9 + 7; // Mod value
// To store the sum
int sum = 0;
// Traverse on the array
for(int i = 0; i < n; i++) {
// To store the minimum of subarray
int mini = arr[i];
/* Nested loop to get all
subarrays starting from index i */
for(int j = i; j < n; j++) {
// Update the minimum value
mini = Math.min(mini, arr[j]);
// Update the sum
sum = (sum + mini) % mod;
}
}
// Return the computed sum
return sum;
}
public static void main(String[] args) {
int[] arr = {3, 1, 2, 5};
/* Creating an instance of
Solution class */
Solution sol = new Solution();
/* Function call to find the sum of the
minimum value in each subarray */
int ans = sol.sumSubarrayMins(arr);
System.out.println("The sum of minimum value in each subarray is: " + ans);
}
}
class Solution:
def sumSubarrayMins(self, arr):
# Size of array
n = len(arr)
mod = int(1e9 + 7) # Mod value
# To store the sum
total_sum = 0
# Traverse on the array
for i in range(n):
# To store the minimum of subarray
mini = arr[i]
# Nested loop to get all
# subarrays starting from index i
for j in range(i, n):
# Update the minimum value
mini = min(mini, arr[j])
# Update the sum
total_sum = (total_sum + mini) % mod
# Return the computed sum
return total_sum
# Main function to test the solution
if __name__ == "__main__":
arr = [3, 1, 2, 5]
# Creating an instance of Solution class
sol = Solution()
# Function call to find the sum of the
# minimum value in each subarray
ans = sol.sumSubarrayMins(arr)
print("The sum of minimum value in each subarray is:", ans)
class Solution {
/* Function to find the sum of the
minimum value in each subarray */
sumSubarrayMins(arr) {
// Size of array
let n = arr.length;
let mod = 1e9 + 7; // Mod value
// To store the sum
let sum = 0;
// Traverse on the array
for (let i = 0; i < n; i++) {
// To store the minimum of subarray
let mini = arr[i];
/* Nested loop to get all
subarrays starting from index i */
for (let j = i; j < n; j++) {
// Update the minimum value
mini = Math.min(mini, arr[j]);
// Update the sum
sum = (sum + mini) % mod;
}
}
// Return the computed sum
return sum;
}
}
// Main function to test the solution
const arr = [3, 1, 2, 5];
/* Creating an instance of
Solution class */
const sol = new Solution();
/* Function call to find the sum of the
minimum value in each subarray */
const ans = sol.sumSubarrayMins(arr);
console.log("The sum of minimum value in each subarray is:", ans);
Time Complexity: O(N2)
Using two nested loops.
Space Complexity: O(1)
Using only a couple of variables.
Pre Requisites: Next Greater Element
Consider the following example:
Hence it is clear that instead of generating all the subarrays and finding the minimum in each subarray to find the sum, we can get the required sum by finding the number of times(frequency) an element in the array will be considered in sum.
Considering the above dry run, we can see that:
ind - (psee[ind] + 1) + 1
, i.e., ind - psee[ind].
and,
(nse[ind] - 1) - ind + 1
, i.e., nse[ind] - ind.
(ind - psee[ind]) * (nse[ind] - ind).
(Yet to insert)
109 + 7
to handle large numbers.#include <bits/stdc++.h>
using namespace std;
class Solution {
private:
/* Function to find the indices of
next smaller elements */
vector<int> findNSE(vector<int> &arr) {
// Size of array
int n = arr.size();
// To store the answer
vector<int> ans(n);
// Stack
stack<int> st;
// Start traversing from the back
for(int i = n - 1; i >= 0; i--) {
// Get the current element
int currEle = arr[i];
/* Pop the elements in the stack until
the stack is not empty and the top
element is not the smaller element */
while(!st.empty() && arr[st.top()] >= arr[i]){
st.pop();
}
// Update the answer
ans[i] = !st.empty() ? st.top() : n;
/* Push the index of current
element in the stack */
st.push(i);
}
// Return the answer
return ans;
}
/* Function to find the indices of
previous smaller or equal elements */
vector<int> findPSEE(vector<int> &arr) {
// Size of array
int n = arr.size();
// To store the answer
vector<int> ans(n);
// Stack
stack<int> st;
// Traverse on the array
for(int i=0; i < n; i++) {
// Get the current element
int currEle = arr[i];
/* Pop the elements in the stack until
the stack is not empty and the top
elements are greater than the current element */
while(!st.empty() && arr[st.top()] > arr[i]){
st.pop();
}
// Update the answer
ans[i] = !st.empty() ? st.top() : -1;
/* Push the index of current
element in the stack */
st.push(i);
}
// Return the answer
return ans;
}
public:
/* Function to find the sum of the
minimum value in each subarray */
int sumSubarrayMins(vector<int> &arr) {
vector<int> nse =
findNSE(arr);
vector<int> psee =
findPSEE(arr);
// Size of array
int n = arr.size();
int mod = 1e9 + 7; // Mod value
// To store the sum
int sum = 0;
// Traverse on the array
for(int i=0; i < n; i++) {
// Count of first type of subarrays
int left = i - psee[i];
// Count of second type of subarrays
int right = nse[i] - i;
/* Count of subarrays where
current element is minimum */
long long freq = left*right*1LL;
// Contribution due to current element
int val = (freq*arr[i]*1LL) % mod;
// Updating the sum
sum = (sum + val) % mod;
}
// Return the computed sum
return sum;
}
};
int main() {
vector<int> arr = {3, 1, 2, 5};
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to find the sum of the
minimum value in each subarray */
int ans = sol.sumSubarrayMins(arr);
cout << "The sum of minimum value in each subarray is: " << ans;
return 0;
}
import java.util.*;
class Solution {
/* Function to find the indices of
next smaller elements */
private int[] findNSE(int[] arr) {
// Size of array
int n = arr.length;
// To store the answer
int[] ans = new int[n];
// Stack
Stack<Integer> st = new Stack<>();
// Start traversing from the back
for (int i = n - 1; i >= 0; i--) {
// Get the current element
int currEle = arr[i];
/* Pop the elements in the stack until
the stack is not empty and the top
element is not the smaller element */
while (!st.isEmpty() && arr[st.peek()] >= arr[i]) {
st.pop();
}
// Update the answer
ans[i] = !st.isEmpty() ? st.peek() : n;
/* Push the index of current
element in the stack */
st.push(i);
}
// Return the answer
return ans;
}
/* Function to find the indices of
previous smaller or equal elements */
private int[] findPSEE(int[] arr) {
// Size of array
int n = arr.length;
// To store the answer
int[] ans = new int[n];
// Stack
Stack<Integer> st = new Stack<>();
// Traverse on the array
for (int i = 0; i < n; i++) {
// Get the current element
int currEle = arr[i];
/* Pop the elements in the stack until
the stack is not empty and the top
elements are greater than the current element */
while (!st.isEmpty() && arr[st.peek()] > arr[i]) {
st.pop();
}
// Update the answer
ans[i] = !st.isEmpty() ? st.peek() : -1;
/* Push the index of current
element in the stack */
st.push(i);
}
// Return the answer
return ans;
}
/* Function to find the sum of the
minimum value in each subarray */
public int sumSubarrayMins(int[] arr) {
int[] nse = findNSE(arr);
int[] psee = findPSEE(arr);
// Size of array
int n = arr.length;
int mod = (int)1e9 + 7; // Mod value
// To store the sum
int sum = 0;
// Traverse on the array
for (int i = 0; i < n; i++) {
// Count of first type of subarrays
int left = i - psee[i];
// Count of second type of subarrays
int right = nse[i] - i;
/* Count of subarrays where
current element is minimum */
long freq = left * right * 1L;
// Contribution due to current element
int val = (int)((freq * arr[i]) % mod);
// Updating the sum
sum = (sum + val) % mod;
}
// Return the computed sum
return sum;
}
public static void main(String[] args) {
int[] arr = {3, 1, 2, 5};
// Creating an instance of Solution class
Solution sol = new Solution();
// Function call to find the sum of the minimum value in each subarray
int ans = sol.sumSubarrayMins(arr);
System.out.println("The sum of minimum value in each subarray is: " + ans);
}
}
class Solution:
# Function to find the indices
# of next smaller elements
def findNSE(self, arr):
# Size of array
n = len(arr)
# To store the answer
ans = [0] * n
# Stack
st = []
# Start traversing from the back
for i in range(n - 1, -1, -1):
# Get the current element
currEle = arr[i]
# Pop the elements in the stack until
# the stack is not empty and the top
# element is not the smaller element
while st and arr[st[-1]] >= arr[i]:
st.pop()
# Update the answer
ans[i] = st[-1] if st else n
# Push the index of current
# element in the stack
st.append(i)
# Return the answer
return ans
# Function to find the indices of
# previous smaller or equal elements
def findPSEE(self, arr):
# Size of array
n = len(arr)
# To store the answer
ans = [0] * n
# Stack
st = []
# Traverse on the array
for i in range(n):
# Get the current element
currEle = arr[i]
# Pop the elements in the stack until
# the stack is not empty and the top
# elements are greater than the current element
while st and arr[st[-1]] > arr[i]:
st.pop()
# Update the answer
ans[i] = st[-1] if st else -1
# Push the index of current
# element in the stack
st.append(i)
# Return the answer
return ans
# Function to find the sum of the
# minimum value in each subarray
def sumSubarrayMins(self, arr):
nse = self.findNSE(arr)
psee = self.findPSEE(arr)
# Size of array
n = len(arr)
mod = int(1e9 + 7) # Mod value
# To store the sum
total_sum = 0
# Traverse on the array
for i in range(n):
# Count of first type of subarrays
left = i - psee[i]
# Count of second type of subarrays
right = nse[i] - i
# Count of subarrays where
# current element is minimum
freq = left * right * 1
# Contribution due to current element
val = (freq * arr[i]) % mod
# Updating the sum
total_sum = (total_sum + val) % mod
# Return the computed sum
return total_sum
# Main function to test the solution
if __name__ == "__main__":
arr = [3, 1, 2, 5]
# Creating an instance of Solution class
sol = Solution()
# Function call to find the sum of the
# minimum value in each subarray
ans = sol.sumSubarrayMins(arr)
print("The sum of minimum value in each subarray is:", ans)
class Solution {
/* Function to find the indices
of next smaller elements */
findNSE(arr) {
// Size of array
const n = arr.length;
// To store the answer
const ans = new Array(n).fill(0);
// Stack
const st = [];
// Start traversing from the back
for (let i = n - 1; i >= 0; i--) {
// Get the current element
const currEle = arr[i];
// Pop the elements in the stack until
// the stack is not empty and the top
// element is not the smaller element
while (st.length > 0 && arr[st[st.length - 1]] >= arr[i]) {
st.pop();
}
// Update the answer
ans[i] = st.length > 0 ? st[st.length - 1] : n;
/* Push the index of current
element in the stack */
st.push(i);
}
// Return the answer
return ans;
}
/* Function to find the indices of
previous smaller or equal elements */
findPSEE(arr) {
// Size of array
const n = arr.length;
// To store the answer
const ans = new Array(n).fill(0);
// Stack
const st = [];
// Traverse on the array
for (let i = 0; i < n; i++) {
// Get the current element
const currEle = arr[i];
// Pop the elements in the stack until
// the stack is not empty and the top
// elements are greater than the current element
while (st.length > 0 && arr[st[st.length - 1]] > arr[i]) {
st.pop();
}
// Update the answer
ans[i] = st.length > 0 ? st[st.length - 1] : -1;
/* Push the index of current
element in the stack */
st.push(i);
}
// Return the answer
return ans;
}
/* Function to find the sum of
the minimum value in each subarray */
sumSubarrayMins(arr) {
const nse = this.findNSE(arr);
const psee = this.findPSEE(arr);
// Size of array
const n = arr.length;
const mod = 1e9 + 7; // Mod value
// To store the sum
let sum = 0;
// Traverse on the array
for (let i = 0; i < n; i++) {
// Count of first type of subarrays
const left = i - psee[i];
// Count of second type of subarrays
const right = nse[i] - i;
/* Count of subarrays where
current element is minimum */
const freq = left * right * 1;
// Contribution due to current element
const val = (freq * arr[i]) % mod;
// Updating the sum
sum = (sum + val) % mod;
}
// Return the computed sum
return sum;
}
}
// Main function to test the solution
const arr = [3, 1, 2, 5];
/* Creating an instance of
Solution class */
const sol = new Solution();
/* Function call to find the sum of the
minimum value in each subarray */
const ans = sol.sumSubarrayMins(arr);
console.log("The sum of minimum value in each subarray is:", ans);
Time Complexity: O(N) (where N is the size of given array)
Space Complexity: O(N)
Q: How does the left boundary (L[i]) calculation work?
A: It finds how many previous elements are greater than the current one, meaning arr[i] is the minimum for those subarrays.
Q: Can negative numbers appear in the array?
A: Yes, but since we take modulo (10⁹ + 7) at the end, the calculations remain valid.
Q: How would the approach change for the sum of the maximum elements in each subarray?
A: Instead of a monotonic increasing stack, use a monotonic decreasing stack.