Skip to content
Related Articles

Related Articles

Improve Article

Count distinct elements from a range of a sorted sequence from a given frequency array

  • Difficulty Level : Expert
  • Last Updated : 12 Jun, 2021

Given two integers L and R and an array arr[] consisting of N positive integers( 1-based indexing ) such that the frequency of ith element of a sorted sequence, say A[], is arr[i]. The task is to find the number of distinct elements from the range [L, R] in the sequence A[].

Examples:

Input: arr[] = {3, 6, 7, 1, 8}, L = 3, R = 7
Output: 2
Explanation: From the given frequency array, the sorted array will be {1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, ….}. Now, the number of distinct elements from the range [3, 7] is 2( = {1, 2}).

Input: arr[] = {1, 2, 3, 4}, L = 3, R = 4
Output: 1

 

Naive Approach: The simplest approach to solve the given problem is to construct the sorted sequence from the given array arr[] using the given frequencies and then traverse the constructed array over the range [L, R] to count the number of distinct elements.



Time Complexity: O(N + R – L)
Auxiliary Space: O(S), where S is the sum of the array elements.

Efficient Approach: The above approach can be optimized by using the Binary Search and the prefix sum technique to find the number of distinct elements over the range [L, R]. Follow the steps below to solve the given problem:

  • Initialize an auxiliary array, say prefix[] that stores the prefix sum of the given array elements.
  • Find the prefix sum of the given array and stored it in the array prefix[].
  • By using binary search, find the first index at which the value in prefix[] is at least L, say left.
  • By using binary search, find the first index at which the value in prefix[] is at least R, say right.
  • After completing the above steps, print the value of (right – left + 1) as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include<bits/stdc++.h>
using namespace std;
 
// Function to find the first index
// with value is at least element
int binarysearch(int array[], int right,
                 int element)
{
     
    // Update the value of left
    int left = 1;
 
    // Update the value of right
      
    // Binary search for the element
    while (left <= right)
    {
         
        // Find the middle element
        int mid = (left + right / 2);
 
        if (array[mid] == element)
        {
            return mid;
        }
 
        // Check if the value lies
        // between the elements at
        // index mid - 1 and mid
        if (mid - 1 > 0 && array[mid] > element &&
           array[mid - 1] < element)
        {
            return mid;
        }
 
        // Check in the right subarray
        else if (array[mid] < element)
        {
             
            // Update the value
            // of left
            left = mid + 1;
        }
 
        // Check in left subarray
        else
        {
             
            // Update the value of
            // right
            right = mid - 1;
        }
    }
    return 1;
}
 
// Function to count the number of
// distinct elements over the range
// [L, R] in the sorted sequence
void countDistinct(vector<int> arr,
                          int L, int R)
{
     
    // Stores the count of distinct
    // elements
    int count = 0;
 
    // Create the prefix sum array
    int pref[arr.size() + 1];
 
    for(int i = 1; i <= arr.size(); ++i)
    {
         
        // Update the value of count
        count += arr[i - 1];
 
        // Update the value of pref[i]
        pref[i] = count;
    }
 
    // Calculating the first index
    // of L and R using binary search
    int left = binarysearch(pref, arr.size() + 1, L);
    int right = binarysearch(pref, arr.size() + 1, R);
 
    // Print the resultant count
    cout << right - left + 1;
}
 
// Driver Code
int main()
{
    vector<int> arr{ 3, 6, 7, 1, 8 };
    int L = 3;
    int R = 7;
     
    countDistinct(arr, L, R);
}
 
// This code is contributed by ipg2016107

Java




// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function to find the first index
    // with value is at least element
    static int binarysearch(int array[],
                            int element)
    {
        // Update the value of left
        int left = 1;
 
        // Update the value of right
        int right = array.length - 1;
 
        // Binary search for the element
        while (left <= right) {
 
            // Find the middle element
            int mid = (int)(left + right / 2);
 
            if (array[mid] == element) {
                return mid;
            }
 
            // Check if the value lies
            // between the elements at
            // index mid - 1 and mid
            if (mid - 1 > 0
                && array[mid] > element
                && array[mid - 1] < element) {
 
                return mid;
            }
 
            // Check in the right subarray
            else if (array[mid] < element) {
 
                // Update the value
                // of left
                left = mid + 1;
            }
 
            // Check in left subarray
            else {
 
                // Update the value of
                // right
                right = mid - 1;
            }
        }
 
        return 1;
    }
 
    // Function to count the number of
    // distinct elements over the range
    // [L, R] in the sorted sequence
    static void countDistinct(int arr[],
                              int L, int R)
    {
        // Stores the count of distinct
        // elements
        int count = 0;
 
        // Create the prefix sum array
        int pref[] = new int[arr.length + 1];
 
        for (int i = 1; i <= arr.length; ++i) {
 
            // Update the value of count
            count += arr[i - 1];
 
            // Update the value of pref[i]
            pref[i] = count;
        }
 
        // Calculating the first index
        // of L and R using binary search
        int left = binarysearch(pref, L);
        int right = binarysearch(pref, R);
 
        // Print the resultant count
        System.out.println(
            (right - left) + 1);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 3, 6, 7, 1, 8 };
        int L = 3;
        int R = 7;
        countDistinct(arr, L, R);
    }
}

Python3




# Python3 program for the above approach
 
# Function to find the first index
# with value is at least element
def binarysearch(array,  right,
                 element):
 
    # Update the value of left
    left = 1
 
    # Update the value of right
 
    # Binary search for the element
    while (left <= right):
 
        # Find the middle element
        mid = (left + right // 2)
 
        if (array[mid] == element):
            return mid
 
        # Check if the value lies
        # between the elements at
        # index mid - 1 and mid
        if (mid - 1 > 0 and array[mid] > element and
                        array[mid - 1] < element):
            return mid
 
        # Check in the right subarray
        elif (array[mid] < element):
 
            # Update the value
            # of left
            left = mid + 1
 
        # Check in left subarray
        else:
 
            # Update the value of
            # right
            right = mid - 1
 
    return 1
 
# Function to count the number of
# distinct elements over the range
# [L, R] in the sorted sequence
def countDistinct(arr, L, R):
 
    # Stores the count of distinct
    # elements
    count = 0
 
    # Create the prefix sum array
    pref = [0] * (len(arr) + 1)
 
    for i in range(1, len(arr) + 1):
 
        # Update the value of count
        count += arr[i - 1]
 
        # Update the value of pref[i]
        pref[i] = count
 
    # Calculating the first index
    # of L and R using binary search
    left = binarysearch(pref, len(arr) + 1, L)
    right = binarysearch(pref, len(arr) + 1, R)
 
    # Print the resultant count
    print(right - left + 1)
 
# Driver Code
if __name__ == "__main__":
 
    arr = [ 3, 6, 7, 1, 8 ]
    L = 3
    R = 7
 
    countDistinct(arr, L, R)
 
# This code is contributed by ukasp

C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find the first index
// with value is at least element
static int binarysearch(int []array, int right,
                        int element)
{
     
    // Update the value of left
    int left = 1;
 
    // Update the value of right
      
    // Binary search for the element
    while (left <= right)
    {
         
        // Find the middle element
        int mid = (left + right / 2);
 
        if (array[mid] == element)
        {
            return mid;
        }
 
        // Check if the value lies
        // between the elements at
        // index mid - 1 and mid
        if (mid - 1 > 0 && array[mid] > element &&
            array[mid - 1] < element)
        {
            return mid;
        }
 
        // Check in the right subarray
        else if (array[mid] < element)
        {
             
            // Update the value
            // of left
            left = mid + 1;
        }
 
        // Check in left subarray
        else
        {
             
            // Update the value of
            // right
            right = mid - 1;
        }
    }
    return 1;
}
 
// Function to count the number of
// distinct elements over the range
// [L, R] in the sorted sequence
static void countDistinct(List<int> arr,
                          int L, int R)
{
     
    // Stores the count of distinct
    // elements
    int count = 0;
 
    // Create the prefix sum array
    int []pref = new int[arr.Count + 1];
 
    for(int i = 1; i <= arr.Count; ++i)
    {
         
        // Update the value of count
        count += arr[i - 1];
 
        // Update the value of pref[i]
        pref[i] = count;
    }
 
    // Calculating the first index
    // of L and R using binary search
    int left = binarysearch(pref, arr.Count + 1, L);
    int right = binarysearch(pref, arr.Count + 1, R);
 
    // Print the resultant count
    Console.Write(right - left + 1);
}
 
// Driver Code
public static void Main()
{
    List<int> arr = new List<int>(){ 3, 6, 7, 1, 8 };
    int L = 3;
    int R = 7;
     
    countDistinct(arr, L, R);
}
}
 
// This code is contributed by SURENDRA_GANGWAR

Javascript




<script>
 
// Javascript program for the above approach
 
// Function to find the first index
// with value is at least element
function binarysearch(array, right, element)
{
     
    // Update the value of left
    let left = 1;
  
    // Update the value of right
       
    // Binary search for the element
    while (left <= right)
    {
         
        // Find the middle element
        let mid = Math.floor((left + right / 2));
  
        if (array[mid] == element)
        {
            return mid;
        }
  
        // Check if the value lies
        // between the elements at
        // index mid - 1 and mid
        if (mid - 1 > 0 && array[mid] > element &&
            array[mid - 1] < element)
        {
            return mid;
        }
  
        // Check in the right subarray
        else if (array[mid] < element)
        {
              
            // Update the value
            // of left
            left = mid + 1;
        }
  
        // Check in left subarray
        else
        {
              
            // Update the value of
            // right
            right = mid - 1;
        }
    }
    return 1;
}
  
// Function to count the number of
// distinct elements over the range
// [L, R] in the sorted sequence
function countDistinct(arr, L, R)
{
     
    // Stores the count of distinct
    // elements
    let count = 0;
  
    // Create the prefix sum array
    let pref = Array.from(
        {length: arr.length + 1}, (_, i) => 0);
  
    for(let i = 1; i <= arr.length; ++i)
    {
         
        // Update the value of count
        count += arr[i - 1];
  
        // Update the value of pref[i]
        pref[i] = count;
    }
  
    // Calculating the first index
    // of L and R using binary search
    let left = binarysearch(pref, arr.length + 1, L);
    let right = binarysearch(pref, arr.length + 1, R);
  
        // Print the resultant count
        document.write((right - left) + 1);
}
 
// Driver Code
let arr = [ 3, 6, 7, 1, 8 ];
let L = 3;
let R = 7;
 
countDistinct(arr, L, R);
 
// This code is contributed by susmitakundugoaldanga
 
</script>
Output: 
2

 

Time Complexity: O(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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :