Given an array arr[], Find the number of subarrays whose first element is not greater than other elements of the subarray.
Examples:
Input: arr[] = [1, 2, 1]
Output: 5
Explanation: All subarray are: {1}, {1, 2}, {1, 2, 1}, {2}, {2, 1}, {1}
From above subarray the following meets the condition: {1}, {1, 2}, {1, 2, 1}, {2}, {1}Input: arr[] = [1, 3, 5, 2]
Output: 8
Explanation: We have the following subarrays which meet the condition:
{1}, {1, 3}, {1, 3, 5}, {1, 3, 5, 2}, {3}, {3, 5}, {5}, {2}
Table of Content
[Naive Approach] With Recalculated Minimum - O(n3) Time and O(1) Space
The naive approach is to run a nested loop and find all the subarrays with first element not bigger than the other elements in the subarray.
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
int countSubarrays(vector<int>& arr) {
int n = arr.size();
// Cnt is initialised to n because
// atleast n subarrays will be there
int cnt = n;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// Minimum element from
// [start+1, end] of each subarray
int mini_ele = *min_element(begin(arr) + i + 1,
begin(arr) + j + 1);
// Checking if minimum of
// elements from [start+1, end] is
// not smaller than start element
// updating the count of subarrays
if (mini_ele >= arr[i])
cnt++;
}
}
return cnt;
}
int main(){
vector<int> arr = { 1, 3, 5, 2 };
cout << countSubarrays(arr) << "\n";
return 0;
}
class GFG{
static int min_element(int arr[], int left, int right){
int x = Integer.MAX_VALUE;
for(int i=left;i<right;i++)
{
x=Math.min(x,arr[i]);
}
return x;
}
static int countSubarrays(int arr[]){
int n = arr.length;
// Cnt is initialised to n because
// atleast n subarrays will be there
int cnt = n;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
// Minimum element from
// [start+1, end] of each subarray
int mini_ele = min_element(arr,i+1,j+1);
// Checking if minimum of
// elements from [start+1, end] is
// not smaller than start element
// updating the count of subarrays
if (mini_ele >= arr[i])
cnt++;
}
}
return cnt;
}
public static void main(String[] args) {
int arr[] = {1, 3, 5, 2};
System.out.println(countSubarrays(arr) );
}
}
import sys
def min_element(arr, left, right):
x = sys.maxsize
for i in range(left, right):
x = min(arr[i], x)
return x
def countSubarrays(arr):
n = len(arr)
# Cnt is initialised to n because
# atleast n subarrays will be there
cnt = n
for i in range(n):
for j in range(i+1,n):
# Minimum element from
# [start+1, end] of each subarray
mini_ele = min_element(arr ,i + 1, j + 1)
# Checking if minimum of
# elements from [start+1, end] is
# not smaller than start element
# updating the count of subarrays
if (mini_ele >= arr[i]):
cnt += 1
return cnt
if __name__ == "__main__":
arr = [ 1, 3, 5, 2 ]
print(countSubarrays(arr))
using System;
using System.Collections.Generic;
public class GFG{
static int min_element(int []arr, int left, int right){
int x = int.MaxValue;
for(int i=left;i<right;i++){
x=Math.Min(x,arr[i]);
}
return x;
}
static int countSubarrays(int []arr){
int n = arr.Length;
// Cnt is initialised to n because
// atleast n subarrays will be there
// which is single element itself
int cnt = n;
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++) {
// Minimum element from
// [start+1, end] of each subarray
int mini_ele = min_element(arr,i+1,j+1);
// Checking if minimum of
// elements from [start+1, end] is
// not smaller than start element
// updating the count of subarrays
if (mini_ele >= arr[i])
cnt++;
}
}
return cnt;
}
public static void Main(String[] args){
int []arr = {1, 3, 5, 2};
Console.WriteLine(countSubarrays(arr) );
}
}
function min_element(arr,left,right){
let x = Number.MAX_VALUE
for(let i=left;i<right;i++){
x = Math.min(arr[i],x)
}
return x
}
function countSubarrays(arr){
let n = arr.length
// Cnt is initialised to n because
// atleast n subarrays will be there
// which is single element itself
let cnt = n
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
// Minimum element from
// [start+1, end] of each subarray
let mini_ele = min_element(arr ,i + 1, j + 1);
// Checking if minimum of
// elements from [start+1, end] is
// not smaller than start element
// updating the count of subarrays
if (mini_ele >= arr[i])
cnt++;
}
}
return cnt;
}
// Driver Code
let arr = [ 1, 3, 5, 2 ];
console.log(countSubarrays(arr));
Output
8
[Better Approach] With Running Minimum - O(n2) Time and O(1) Space
We don’t need to find the minimum separately after two loops. While expanding the subarray, we can directly maintain the running minimum and check if it stays ≥ the first element.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int countSubarrays(vector<int>& arr) {
int n = arr.size();
int cnt = n;
for (int i = 0; i < n; i++) {
int mini = arr[i];
for (int j = i + 1; j < n; j++) {
mini = min(mini, arr[j]);
if (mini >= arr[i]) {
cnt++;
} else {
// stop if a smaller element is found
break;
}
}
}
return cnt;
}
int main() {
vector<int> arr = {1, 3, 5, 2};
cout << countSubarrays(arr) << "\n";
return 0;
}
class GFG {
static int countSubarrays(int[] arr) {
int n = arr.length;
int cnt = n;
for (int i = 0; i < n; i++) {
int mini = arr[i];
for (int j = i + 1; j < n; j++) {
mini = Math.min(mini, arr[j]);
if (mini >= arr[i]) {
cnt++;
} else {
// stop if a smaller element is found
break;
}
}
}
return cnt;
}
public static void main(String[] args) {
int[] arr = {1, 3, 5, 2};
System.out.println(countSubarrays(arr));
}
}
def countSubarrays(arr):
n = len(arr)
cnt = n
for i in range(n):
mini = arr[i]
for j in range(i + 1, n):
mini = min(mini, arr[j])
if mini >= arr[i]:
cnt += 1
else:
# stop if a smaller element is found
break
return cnt
if __name__ == "__main__":
arr = [1, 3, 5, 2]
print(countSubarrays(arr))
using System;
class GFG{
static int countSubarrays(int[] arr){
int n = arr.Length;
int cnt = n;
for (int i = 0; i < n; i++){
int mini = arr[i];
for (int j = i + 1; j < n; j++){
mini = Math.Min(mini, arr[j]);
if (mini >= arr[i]){
cnt++;
}
else{
// stop if a smaller element is found
break;
}
}
}
return cnt;
}
public static void Main(){
int[] arr = { 1, 3, 5, 2 };
Console.WriteLine(countSubarrays(arr));
}
}
function countSubarrays(arr) {
let n = arr.length;
let cnt = n;
for (let i = 0; i < n; i++) {
let mini = arr[i];
for (let j = i + 1; j < n; j++) {
mini = Math.min(mini, arr[j]);
if (mini >= arr[i]) {
cnt++;
} else {
// stop if a smaller element is found
break;
}
}
}
return cnt;
}
// Driver Code
let arr = [1, 3, 5, 2];
console.log(countSubarrays(arr));
Output
8
[Efficient Approach] Using stack - O(n) Time and O(n) Space
The efficient approach is based on the concept of finding the next smaller element on the right of an element.
Working:
- We use a monotonic stack to get the index of the next smaller of each element on the right because we want the subarray with first element as the minimum element.
- The total subarray's in the range [i, j] having i as the starting index is (j - i).
- Compute the next smaller index for every index i, add (j-i) for each of them and keep updating the total count of valid subarrays.
#include <iostream>
#include<stack>
#include<vector>
using namespace std;
int countSubarrays(vector<int>& arr){
stack<int> st;
int ans = 0;
int n = arr.size();
for (int i = n - 1; i >= 0; i--) {
while (!st.empty() and arr[st.top()] >= arr[i])
st.pop();
// The index of next smaller element
// starting from i'th index
int last = (st.empty() ? n : st.top());
// Adding the number of subarray which
// can be formed in the range [i, last]
ans += (last - i);
st.push(i);
}
return ans;
}
int main(){
vector<int> arr = { 1, 3, 5, 2 };
cout << countSubarrays(arr) << "\n";
return 0;
}
import java.util.Stack;
class GFG {
static int countSubarrays(int arr[]){
Stack<Integer> st = new Stack<Integer>();
int ans = 0;
int n = arr.length;
for (int i = n - 1; i >= 0; i--) {
while (st.empty() == false
&& arr[st.peek()] >= arr[i])
st.pop();
// The index of next smaller element
// starting from i'th index
int last = ((st.empty() == true) ? n : st.peek());
// Adding the number of subarray which
// can be formed in the range [i, last]
ans += (last - i);
st.push(i);
}
return ans;
}
public static void main(String[] args){
int arr[] = new int[] { 1, 3, 5, 2 };
System.out.println(countSubarrays(arr));
}
}
def countSubarrays(arr):
st = []
ans = 0
n = len(arr)
for i in range(n - 1, -1, -1):
while (len(st) != 0 and arr[st[-1]] >= arr[i]):
st.pop()
# The index of next smaller element
# starting from i'th index
if (len(st) == 0):
last = n
else:
last = st[-1]
# Adding the number of subarray which
# can be formed in the range [i, last]
ans += (last - i)
st.append(i)
return ans
if __name__ == "__main__":
arr = [1, 3, 5, 2]
print(countSubarrays(arr))
using System;
using System.Collections.Generic;
class GFG{
static int countSubarrays(List<int> arr) {
Stack<int> st = new Stack<int>();
int ans = 0;
int n = arr.Count;
for (int i = n - 1 ; i >= 0 ; i--) {
while (st.Count > 0 && arr[st.Peek()] >= arr[i]){
st.Pop();
}
// The index of next smaller element
// starting from i'th index
int last = (st.Count == 0 ? n : st.Peek());
// Adding the number of subarray which
// can be formed in the range [i, last]
ans += (last - i);
st.Push(i);
}
return ans;
}
public static void Main(string[] args){
List<int> arr = new List<int>{
1, 3, 5, 2
};
Console.Write(countSubarrays(arr));
}
}
function countSubarrays(arr) {
let st = [];
let ans = 0;
let n = arr.length;
for (let i = n - 1; i >= 0; i--) {
while (st.length != 0 && arr[st[st.length - 1]] >= arr[i])
st.pop();
// The index of next smaller element
// starting from i'th index
let last = (st.length == 0 ? n : st[st.length - 1]);
// Adding the number of subarray which
// can be formed in the range [i, last]
ans += (last - i);
st.push(i);
}
return ans;
}
// Driver Code
let arr = [1, 3, 5, 2];
console.log(countSubarrays(arr));
Output
8