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 for every array element arr[i], count the number of subarrays in which it is the smallest element.



Time Complexity: O(N3)
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:

  1. Store all the indices of array elements in a Map.
  2. Sort the array in increasing order.
  3. Initialize an array boundary[].
  4. 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].
  5. Now, using the above formula, find the number of subarrays and keep track of that count in the resultant array.
  6. After completing the above steps, print all the counts stored in the resultant array.

Below is the implementation of the above approach:

C++14

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++14 program for the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to find the boundary of every
// element within which it is minimum
int binaryInsert(vector<int> &boundary, int i)
{
    int l = 0;
    int r = boundary.size() - 1;
  
    // Perform Binary Search
    while (l <= r)
    {
          
        // Find mid m
        int m = (l + r) / 2;
  
        // Update l
        if (boundary[m] < i)
            l = m + 1;
  
        // Update r
        else
            r = m - 1;
    }
  
    // Inserting the index
    boundary.insert(boundary.begin() + l, i);
  
    return l;
}
  
// Function to required count subarrays
vector<int> countingSubarray(vector<int> arr, int n)
{
      
    // Stores the indices of element
    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());
  
    // Initialize the output array
    vector<int> ans(n, 0);
  
    for(int num : arr)
    {
        int i = binaryInsert(boundary, index[num]);
  
        // Left boundary, till the
        // element is smallest
        int l = boundary[i] - boundary[i - 1] - 1;
  
        // Right boundary, till the
        // element is smallest
        int r = boundary[i + 1] - boundary[i] - 1;
  
        // Calculate the number of subarrays
        // based on its boundary
        int cnt = l + r + l * r + 1;
  
        // Adding cnt to the ans
        ans[index[num]] += cnt;
    }
    return ans;
}
  
// Driver Code
int main()
{
    int N = 5;
      
    // Given array arr[]
    vector<int> arr = { 3, 2, 4, 1, 5 };
      
    // Function call
    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;
}
  
// This code is contributed by mohit kumar 29

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for the above approach
import java.util.*;
  
class GFG{
    
// Function to find the boundary of every 
// element within which it is minimum 
static int binaryInsert(ArrayList<Integer> boundary, 
                        int i) 
    int l = 0
    int r = boundary.size() - 1
    
    // Perform Binary Search 
    while (l <= r) 
    
        
        // Find mid m 
        int m = (l + r) / 2
    
        // Update l 
        if (boundary.get(m) < i) 
            l = m + 1
    
        // Update r 
        else
            r = m - 1
    
    
    // Inserting the index 
    boundary.add(l, i); 
    
    return l; 
    
// Function to required count subarrays 
static int[] countingSubarray(int[] arr, 
                              int n) 
    
    // Stores the indices of element 
    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);
  
    // Initialize the output array 
    int[] ans = new int[n];
    
    for(int num : arr) 
    
        int i = binaryInsert(boundary, 
                             index.get(num)); 
    
        // Left boundary, till the 
        // element is smallest 
        int l = boundary.get(i) -
                boundary.get(i - 1) - 1
    
        // Right boundary, till the 
        // element is smallest 
        int r = boundary.get(i + 1) -
                boundary.get(i) - 1
    
        // Calculate the number of subarrays 
        // based on its boundary 
        int cnt = l + r + l * r + 1
    
        // Adding cnt to the ans 
        ans[index.get(num)] += cnt; 
    
    return ans; 
}
    
// Driver code
public static void main (String[] args) 
{
    int N = 5
        
    // Given array arr[] 
    int[] arr = { 3, 2, 4, 1, 5 }; 
        
    // Function call 
    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] + "]"); 
}
}
  
// This code is contributed by offbeat

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for the above approach
  
# Function to find the boundary of every
# element within which it is minimum
def binaryInsert(boundary, i):
  
    l = 0
    r = len(boundary) - 1
  
    # Perform Binary Search
    while l <= r:
          
        # Find mid m
        m = (l + r) // 2
          
        # Update l
        if boundary[m] < i:
            l = m + 1
              
        # Update r
        else:
            r = m - 1
  
    # Inserting the index
    boundary.insert(l, i)
  
    return l
  
# Function to required count subarrays
def countingSubarray(arr, n):
  
    # Stores the indices of element
    index = {}
  
    for i in range(n):
        index[arr[i]] = i
  
    boundary = [-1, n]
    arr.sort()
  
    # Initialize the output array
    ans = [0 for i in range(n)]
  
    for num in arr:
        i = binaryInsert(boundary, index[num])
  
        # Left boundary, till the
        # element is smallest
        l = boundary[i] - boundary[i - 1] - 1
  
        # Right boundary, till the
        # element is smallest
        r = boundary[i + 1] - boundary[i] - 1
  
        # Calculate the number of subarrays
        # based on its boundary
        cnt = l + r + l * r + 1
  
        # Adding cnt to the ans
        ans[index[num]] += cnt
  
    return ans
  
  
# Driver Code
  
N = 5
  
# Given array arr[]
arr = [3, 2, 4, 1, 5]
  
# Function Call
print(countingSubarray(arr, N))

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for 
// the above approach
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
     
// Function to find the 
// boundary of every element 
// within which it is minimum 
static int binaryInsert(ArrayList boundary, 
                        int i) 
  int l = 0; 
  int r = boundary.Count - 1; 
  
  // Perform Binary Search 
  while (l <= r) 
  {
    // Find mid m 
    int m = (l + r) / 2; 
  
    // Update l 
    if ((int)boundary[m] < i) 
      l = m + 1; 
  
    // Update r 
    else
      r = m - 1; 
  
  
  // Inserting the index 
  boundary.Insert(l, i); 
  
  return l; 
     
// Function to required count subarrays 
static int[] countingSubarray(int[] arr, 
                              int n) 
  // Stores the indices of element 
  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);
  
  // Initialize the output array 
  int[] ans = new int[n];
  
  foreach(int num in arr) 
  
    int i = binaryInsert(boundary, 
                         index[num]); 
  
    // Left boundary, till the 
    // element is smallest 
    int l = (int)boundary[i] -
            (int)boundary[i - 1] - 1; 
  
    // Right boundary, till the 
    // element is smallest 
    int r = (int)boundary[i + 1] -
            (int)boundary[i] - 1; 
  
    // Calculate the number of  
    // subarrays based on its boundary 
    int cnt = l + r + l * r + 1; 
  
    // Adding cnt to the ans 
    ans[index[num]] += cnt; 
  
  return ans; 
}
     
// Driver code
public static void Main(string[] args) 
{
    int N = 5; 
         
    // Given array arr[] 
    int[] arr = {3, 2, 4, 1, 5}; 
         
    // Function call 
    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] + "]"); 
}
}
  
// This code is contributed by Rutvik_56

chevron_right


Output: 

[1, 4, 1, 8, 1]



Time Complexity: O(N log N) 
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Recommended Posts:


Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.