Count subarrays for every array element in which they are the minimum
Given an array arr[] consisting of N integers, the task is to create an array brr[] of size N where brr[i] represents the count of subarrays in which arr[i] is the smallest element.
Examples:
Input: arr[] = {3, 2, 4}
Output: {1, 3, 1}
Explanation:
For arr[0], there is only one subarray in which 3 is the smallest({3}).
For arr[1], there are three such subarrays where 2 is the smallest({2}, {3, 2}, {2, 4}).
For arr[2], there is only one subarray in which 4 is the smallest({4}).
Input: arr[] = {1, 2, 3, 4, 5}
Output: {5, 4, 3, 2, 1}
Naive Approach: The simplest approach is to generate all subarrays of the given array and while generating the subarray, find the element which is minimum in that subarray and then store the index of that element, then later increment count for that index by 1. Similarly, do this for every subarray
Code-
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > countingSubarray(vector< int > arr, int n)
{
vector< int > ans(n,0);
for ( int i=0;i<n;i++){
int temp=i;
for ( int j=i;j<n;j++){
if (arr[j]<arr[temp]){temp=j;}
ans[temp]++;
}
}
return ans;
}
int main()
{
int N = 5;
vector< int > arr = { 3, 2, 4, 1, 5 };
auto a = countingSubarray(arr, N);
cout << "[" ;
int n = a.size() - 1;
for ( int i = 0; i < n; i++)
cout << a[i] << ", " ;
cout << a[n] << "]" ;
return 0;
}
|
Java
import java.util.*;
class Main {
static List<Integer> countingSubarray(List<Integer> arr, int n) {
List<Integer> ans = new ArrayList<>(Collections.nCopies(n, 0 ));
for ( int i = 0 ; i < n; i++) {
int temp = i;
for ( int j = i; j < n; j++) {
if (arr.get(j) < arr.get(temp)) {
temp = j;
}
ans.set(temp, ans.get(temp) + 1 );
}
}
return ans;
}
public static void main(String[] args) {
int N = 5 ;
List<Integer> arr = Arrays.asList( 3 , 2 , 4 , 1 , 5 );
List<Integer> a = countingSubarray(arr, N);
System.out.print( "[" );
int n = a.size() - 1 ;
for ( int i = 0 ; i < n; i++) {
System.out.print(a.get(i) + ", " );
}
System.out.println(a.get(n) + "]" );
}
}
|
Python3
def countingSubarray(arr, n):
ans = [ 0 ] * n
for i in range (n):
temp = i
for j in range (i, n):
if arr[j] < arr[temp]:
temp = j
ans[temp] + = 1
return ans
N = 5
arr = [ 3 , 2 , 4 , 1 , 5 ]
a = countingSubarray(arr, N)
print (a)
|
C#
using System;
using System.Collections.Generic;
class Program
{
static List< int > CountingSubarray(List< int > arr, int n)
{
List< int > ans = new List< int >( new int [n]);
for ( int i = 0; i < n; i++)
{
int temp = i;
for ( int j = i; j < n; j++)
{
if (arr[j] < arr[temp]) temp = j;
ans[temp]++;
}
}
return ans;
}
static void Main()
{
int N = 5;
List< int > arr = new List< int > { 3, 2, 4, 1, 5 };
List< int > a = CountingSubarray(arr, N);
Console.Write( "[" );
int n = a.Count - 1;
for ( int i = 0; i < n; i++)
{
Console.Write(a[i] + ", " );
}
Console.Write(a[n] + "]" );
}
}
|
Javascript
function countingSubarray(arr, n) {
let ans = new Array(n).fill(0);
for (let i = 0; i < n; i++) {
let temp = i;
for (let j = i; j < n; j++) {
if (arr[j] < arr[temp]) {
temp = j;
}
ans[temp]++;
}
}
return ans;
}
let N = 5;
let arr = [3, 2, 4, 1, 5];
let a = countingSubarray(arr, N);
console.log(a);
|
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the idea is to find the boundary index for every element, up to which it is the smallest element. For each element let L and R be the boundary indices on the left and right side respectively up to which arr[i] is the minimum. Therefore, the count of all subarrays can be calculated by:
(L + R + 1)*(R + 1)
Follow the steps below to solve the problem:
- Store all the indices of array elements in a Map.
- Sort the array in increasing order.
- Initialize an array boundary[].
- Iterate over the sorted array arr[] and simply insert the index of that element using Binary Search. Suppose it got inserted at index i, then its left boundary is boundary[i – 1] and its right boundary is boundary[i + 1].
- Now, using the above formula, find the number of subarrays and keep track of that count in the resultant array.
- After completing the above steps, print all the counts stored in the resultant array.
Below is the implementation of the above approach:
C++14
#include <bits/stdc++.h>
using namespace std;
int binaryInsert(vector< int > &boundary, int i)
{
int l = 0;
int r = boundary.size() - 1;
while (l <= r)
{
int m = (l + r) / 2;
if (boundary[m] < i)
l = m + 1;
else
r = m - 1;
}
boundary.insert(boundary.begin() + l, i);
return l;
}
vector< int > countingSubarray(vector< int > arr, int n)
{
unordered_map< int , int > index;
for ( int i = 0; i < n; i++)
index[arr[i]] = i;
vector< int > boundary = {-1, n};
sort(arr.begin(), arr.end());
vector< int > ans(n, 0);
for ( int num : arr)
{
int i = binaryInsert(boundary, index[num]);
int l = boundary[i] - boundary[i - 1] - 1;
int r = boundary[i + 1] - boundary[i] - 1;
int cnt = l + r + l * r + 1;
ans[index[num]] += cnt;
}
return ans;
}
int main()
{
int N = 5;
vector< int > arr = { 3, 2, 4, 1, 5 };
auto a = countingSubarray(arr, N);
cout << "[" ;
int n = a.size() - 1;
for ( int i = 0; i < n; i++)
cout << a[i] << ", " ;
cout << a[n] << "]" ;
return 0;
}
|
Java
import java.util.*;
class GFG{
static int binaryInsert(ArrayList<Integer> boundary,
int i)
{
int l = 0 ;
int r = boundary.size() - 1 ;
while (l <= r)
{
int m = (l + r) / 2 ;
if (boundary.get(m) < i)
l = m + 1 ;
else
r = m - 1 ;
}
boundary.add(l, i);
return l;
}
static int [] countingSubarray( int [] arr,
int n)
{
Map<Integer, Integer> index = new HashMap<>();
for ( int i = 0 ; i < n; i++)
index.put(arr[i], i);
ArrayList<Integer> boundary = new ArrayList<>();
boundary.add(- 1 );
boundary.add(n);
Arrays.sort(arr);
int [] ans = new int [n];
for ( int num : arr)
{
int i = binaryInsert(boundary,
index.get(num));
int l = boundary.get(i) -
boundary.get(i - 1 ) - 1 ;
int r = boundary.get(i + 1 ) -
boundary.get(i) - 1 ;
int cnt = l + r + l * r + 1 ;
ans[index.get(num)] += cnt;
}
return ans;
}
public static void main (String[] args)
{
int N = 5 ;
int [] arr = { 3 , 2 , 4 , 1 , 5 };
int [] a = countingSubarray(arr, N);
System.out.print( "[" );
int n = a.length - 1 ;
for ( int i = 0 ; i < n; i++)
System.out.print(a[i] + ", " );
System.out.print(a[n] + "]" );
}
}
|
Python3
def binaryInsert(boundary, i):
l = 0
r = len (boundary) - 1
while l < = r:
m = (l + r) / / 2
if boundary[m] < i:
l = m + 1
else :
r = m - 1
boundary.insert(l, i)
return l
def countingSubarray(arr, n):
index = {}
for i in range (n):
index[arr[i]] = i
boundary = [ - 1 , n]
arr.sort()
ans = [ 0 for i in range (n)]
for num in arr:
i = binaryInsert(boundary, index[num])
l = boundary[i] - boundary[i - 1 ] - 1
r = boundary[i + 1 ] - boundary[i] - 1
cnt = l + r + l * r + 1
ans[index[num]] + = cnt
return ans
N = 5
arr = [ 3 , 2 , 4 , 1 , 5 ]
print (countingSubarray(arr, N))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
static int binaryInsert(ArrayList boundary,
int i)
{
int l = 0;
int r = boundary.Count - 1;
while (l <= r)
{
int m = (l + r) / 2;
if (( int )boundary[m] < i)
l = m + 1;
else
r = m - 1;
}
boundary.Insert(l, i);
return l;
}
static int [] countingSubarray( int [] arr,
int n)
{
Dictionary< int ,
int > index = new Dictionary< int ,
int >();
for ( int i = 0; i < n; i++)
index[arr[i]] = i;
ArrayList boundary = new ArrayList();
boundary.Add(-1);
boundary.Add(n);
Array.Sort(arr);
int [] ans = new int [n];
foreach ( int num in arr)
{
int i = binaryInsert(boundary,
index[num]);
int l = ( int )boundary[i] -
( int )boundary[i - 1] - 1;
int r = ( int )boundary[i + 1] -
( int )boundary[i] - 1;
int cnt = l + r + l * r + 1;
ans[index[num]] += cnt;
}
return ans;
}
public static void Main( string [] args)
{
int N = 5;
int [] arr = {3, 2, 4, 1, 5};
int [] a = countingSubarray(arr, N);
Console.Write( "[" );
int n = a.Length - 1;
for ( int i = 0; i < n; i++)
Console.Write(a[i] + ", " );
Console.Write(a[n] + "]" );
}
}
|
Javascript
<script>
function binaryInsert(boundary, i){
let l = 0
let r = boundary.length - 1
while (l <= r){
let m = Math.floor((l + r) / 2)
if (boundary[m] < i)
l = m + 1
else
r = m - 1
}
boundary.splice(l,0, i)
return l
}
function countingSubarray(arr, n){
let index = new Map()
for (let i=0;i<n;i++)
index.set(arr[i] , i)
let boundary = [-1, n]
arr.sort()
let ans = new Array(n).fill(0)
for (let num of arr){
let i = binaryInsert(boundary, index.get(num))
let l = boundary[i] - boundary[i - 1] - 1
let r = boundary[i + 1] - boundary[i] - 1
let cnt = l + r + l * r + 1
ans[index.get(num)] += cnt
}
return ans
}
let N = 5
let arr = [3, 2, 4, 1, 5]
document.write(countingSubarray(arr, N), "</br>" )
</script>
|
Time Complexity: O(N log N)
Auxiliary Space: O(N)
Most efficient approach:
To optimize the above approach we can use a Stack Data Structure.
- Idea is that, For each (1? i ? N) we will try to find index(R) of next smaller element right to it and index(L) of next smaller element left to it.
- Now we have our boundary index(L,R) in which arr[i] is minimum so total number of subarrays for each i(0-base) will be (R-i)*(i-L) .
Below is the implementation of the idea:
C++14
#include <bits/stdc++.h>
using namespace std;
vector< int > countingSubarray(vector< int > arr, int n)
{
vector< int > a(n);
vector< int > nsml(n, -1);
vector< int > nsmr(n, n);
stack< int > st;
for ( int i = n - 1; i >= 0; i--)
{
while (!st.empty() && arr[st.top()] >= arr[i])
st.pop();
nsmr[i] = (!st.empty()) ? st.top() : n;
st.push(i);
}
while (!st.empty())
st.pop();
for ( int i = 0; i < n; i++)
{
while (!st.empty() && arr[st.top()] >= arr[i])
st.pop();
nsml[i] = (!st.empty()) ? st.top() : -1;
st.push(i);
}
for ( int i = 0; i < n; i++)
{
nsml[i]++;
nsmr[i]--;
int r = nsmr[i] - i + 1;
int l = i - nsml[i] + 1;
a[i] = r * l;
}
return a;
}
int main()
{
int N = 5;
vector< int > arr = { 3, 2, 4, 1, 5 };
auto a = countingSubarray(arr, N);
cout << "[" ;
int n = a.size() - 1;
for ( int i = 0; i < n; i++)
cout << a[i] << ", " ;
cout << a[n] << "]" ;
return 0;
}
|
Java
import java.util.*;
public class gfg
{
static int [] countingSubarray( int arr[], int n)
{
int a[] = new int [n];
int nsml[] = new int [n];
Arrays.fill(nsml, - 1 );
int nsmr[] = new int [n];
Arrays.fill(nsmr, n);
Stack<Integer> st = new Stack<Integer>();
for ( int i = n - 1 ; i >= 0 ; i--)
{
while (st.size() > 0 &&
arr[( int )st.peek()] >= arr[i])
st.pop();
nsmr[i] = (st.size() > 0 ) ? ( int )st.peek() : n;
st.push(i);
}
while (st.size() > 0 )
st.pop();
for ( int i = 0 ; i < n; i++)
{
while (st.size() > 0 &&
arr[( int )st.peek()] >= arr[i])
st.pop();
nsml[i] = (st.size() > 0 ) ? ( int )st.peek() : - 1 ;
st.push(i);
}
for ( int i = 0 ; i < n; i++)
{
nsml[i]++;
nsmr[i]--;
int r = nsmr[i] - i + 1 ;
int l = i - nsml[i] + 1 ;
a[i] = r * l;
}
return a;
}
public static void main(String[] args)
{
int N = 5 ;
int arr[] = { 3 , 2 , 4 , 1 , 5 };
int a[] = countingSubarray(arr, N);
System.out.print( "[" );
int n = a.length - 1 ;
for ( int i = 0 ; i < n; i++)
System.out.print(a[i] + ", " );
System.out.print(a[n] + "]" );
}
}
|
Python3
def countingSubarray(arr, n):
a = [ 0 for i in range (n)]
nsml = [ - 1 for i in range (n)]
nsmr = [n for i in range (n)]
st = []
for i in range (n - 1 , - 1 , - 1 ):
while ( len (st) > 0 and arr[st[ - 1 ]] > = arr[i]):
del st[ - 1 ]
if ( len (st) > 0 ):
nsmr[i] = st[ - 1 ]
else :
nsmr[i] = n
st.append(i)
while ( len (st) > 0 ):
del st[ - 1 ]
for i in range (n):
while ( len (st) > 0 and arr[st[ - 1 ]] > = arr[i]):
del st[ - 1 ]
if ( len (st) > 0 ):
nsml[i] = st[ - 1 ]
else :
nsml[i] = - 1
st.append(i)
for i in range (n):
nsml[i] + = 1
nsmr[i] - = 1
r = nsmr[i] - i + 1 ;
l = i - nsml[i] + 1 ;
a[i] = r * l;
return a;
N = 5
arr = [ 3 , 2 , 4 , 1 , 5 ]
a = countingSubarray(arr, N)
print (a)
|
C#
using System;
using System.Collections;
class GFG{
static int [] countingSubarray( int [] arr, int n)
{
int [] a = new int [n];
int [] nsml = new int [n];
Array.Fill(nsml, -1);
int [] nsmr = new int [n];
Array.Fill(nsmr, n);
Stack st = new Stack();
for ( int i = n - 1; i >= 0; i--)
{
while (st.Count > 0 &&
arr[( int )st.Peek()] >= arr[i])
st.Pop();
nsmr[i] = (st.Count > 0) ? ( int )st.Peek() : n;
st.Push(i);
}
while (st.Count > 0)
st.Pop();
for ( int i = 0; i < n; i++)
{
while (st.Count > 0 &&
arr[( int )st.Peek()] >= arr[i])
st.Pop();
nsml[i] = (st.Count > 0) ? ( int )st.Peek() : -1;
st.Push(i);
}
for ( int i = 0; i < n; i++)
{
nsml[i]++;
nsmr[i]--;
int r = nsmr[i] - i + 1;
int l = i - nsml[i] + 1;
a[i] = r * l;
}
return a;
}
static void Main()
{
int N = 5;
int [] arr = { 3, 2, 4, 1, 5 };
int [] a = countingSubarray(arr, N);
Console.Write( "[" );
int n = a.Length - 1;
for ( int i = 0; i < n; i++)
Console.Write(a[i] + ", " );
Console.Write(a[n] + "]" );
}
}
|
Javascript
<script>
function countingSubarray(arr, n)
{
let a = new Array(n);
let nsml = new Array(n);
nsml.fill(-1);
let nsmr = new Array(n);
nsmr.fill(n);
let st = [];
for (let i = n - 1; i >= 0; i--)
{
while (st.length > 0 && arr[st[st.length-1]] >= arr[i])
st.pop();
nsmr[i] = (st.length > 0) ? st[st.length-1] : n;
st.push(i);
}
while (st.length > 0)
st.pop();
for (let i = 0; i < n; i++)
{
while (st.length > 0 &&
arr[st[st.length-1]] >= arr[i])
st.pop();
nsml[i] = (st.length > 0) ? st[st.length-1] : -1;
st.push(i);
}
for (let i = 0; i < n; i++)
{
nsml[i]++;
nsmr[i]--;
let r = nsmr[i] - i + 1;
let l = i - nsml[i] + 1;
a[i] = r * l;
}
return a;
}
let N = 5;
let arr = [ 3, 2, 4, 1, 5 ];
let a = countingSubarray(arr, N);
document.write( "[" );
let n = a.length - 1;
for (let i = 0; i < n; i++)
document.write(a[i] + ", " );
document.write(a[n] + "]" );
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Last Updated :
02 Nov, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...