Open In App

Count subarrays having exactly K elements occurring at least twice

Last Updated : 24 Jun, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] consisting of N integers and a positive integer K, the task is to count the number of subarrays having exactly K elements occurring at least twice.

Examples:

Input: arr[] = {1, 1, 1, 2, 2}, K = 1
Output: 7
Explanation: The subarrays having exactly 1 element occurring at least twice are: 

  1. {1, 1}. Frequency of 1 is 2.
  2. {1, 1, 1}. Frequency of 1 is 3.
  3. {1, 1, 1, 2}. Frequency of 1 is 3.
  4. {1, 1}. Frequency of 1 is 2.
  5. {1, 1, 2}. Frequency of 1 is 2.
  6. {1, 2, 2}. Frequency of 2 is 2.
  7. {2, 2}. Frequency of 2 is 2.

Therefore, the required output is 7.

Input: arr[] = {1, 2, 1, 2, 3}, K = 3

Output: 0

Naive Approach: The simplest approach to solve this problem is to generate all possible subarrays from the given array and count those subarrays having exactly K elements occurring at least twice. After having checked for all the subarrays, print the total number of subarrays obtained. 

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

Efficient Approach: The above approach can be optimized by using Hashing and Two pointers technique. Follow the steps below to solve the problem:

  • Initialize a variable, say cntSub as 0, to store the count of all possible subarrays having exactly K elements occurring at least twice.
  • Initialize two variables, say l as 0, and r as 0, to store the indices of the left and the right boundaries of each subarray respectively.
  • Initialize a Map, say mp, and a Set, say S to store the count of elements in the subarrays and store the elements whose frequency in the subarray is at least 2 respectively.
  • Iterate until r is less than N and perform the following operations:
    • Iterate while r is less than N and the size of the set is at most K:
      • Increment the count of arr[r] in mp and then push the element into set S if mp[arr[r]] is equal to 2.
      • Increment r by 1.
      • If the size of the set S is K then, increment the cntSub by 1.
    • Iterate while l < r and the size of the set is greater than K:
      • Decrement the count of arr[l] in mp and then erase the element from set S if mp[arr[r]] is equal to 1.
      • Increment the cntSub and l by 1.
  • Now iterate while l < N  and the size of the set is K and decrement the count of arr[l] by 1 and if the frequency of arr[l] is 1, then erase the arr[l] from the set.
  • After completing the above steps, print the value of cntSub as the resultant count of subarrays.

Below is the implementation of the above approach:

C++14




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to count the subarrays with
// exactly K elements occurring twice
int cntSubarrays(int A[], int K, int n)
{
    // Stores the count of subarrays
    // having exactly K elements
    // occurring at least twice
    int cntSub = 0;
 
    // Stores the count of
    // integers in the subarray
    map<int, int> mp;
 
    // Stores the indices of left
    // boundary and right boundary
    int l = 0, r = 0;
 
    // Store the elements which occurs
    // atleast twice between [l, r]
    set<int> st;
 
    // Iterate while r < n
    while (r < n) {
 
        // Iterate while r < n
        // and size of st <= K
        while (r < n && st.size() <= K) {
 
            // If mp[A[r]] >= 1
            if (mp[A[r]]) {
                st.insert(A[r]);
            }
 
            // Increment count of A[r]
            mp[A[r]]++;
 
            // Increment r by 1
            r++;
 
            // If st.size() is K
            if (st.size() == K)
                cntSub++;
        }
 
        // Iterate while l < r
        // and st.size() > K
        while (l < r && st.size() > K) {
 
            // Increment cntSub by 1
            cntSub++;
 
            // Decrement cntSub by 1
            mp[A[l]]--;
 
            // If mp[A[l]] = 1
            if (mp[A[l]] == 1) {
                st.erase(st.find(A[l]));
            }
 
            // Increment l by 1
            l++;
        }
    }
 
    // Iterate while l < n  and
    // st.size() == K
    while (l < n && st.size() == K) {
 
        // Increment cntSub by 1
        cntSub++;
 
        mp[A[l]]--;
 
        // If Mp[A[l]] is equal to 1
        if (mp[A[l]] == 1) {
            st.erase(st.find(A[l]));
        }
 
        // Increment l by 1
        l++;
    }
 
    // Return cntSub
    return cntSub;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 1, 1, 2, 2 };
    int K = 1;
    int N = sizeof(arr) / sizeof(arr[0]);
 
    cout << cntSubarrays(arr, K, N);
 
    return 0;
}


Java




// Java program for the above approach
import java.util.*;
class GFG {
 
  // Function to count the subarrays with
  // exactly K elements occurring twice
  static int cntSubarrays(int[] A, int K, int n)
  {
 
    // Stores the count of subarrays
    // having exactly K elements
    // occurring at least twice
    int cntSub = 0;
 
    // Stores the count of
    // integers in the subarray
    HashMap<Integer, Integer> mp
      = new HashMap<Integer, Integer>();
 
    // Stores the indices of left
    // boundary and right boundary
    int l = 0, r = 0;
 
    // Store the elements which occurs
    // atleast twice between [l, r]
    HashSet<Integer> st = new HashSet<Integer>();
 
    // Iterate while r < n
    while (r < n) {
 
      // Iterate while r < n
      // and size of st <= K
      while (r < n && st.size() <= K) {
 
        // If mp[A[r]] >= 1
        if (mp.containsKey(A[r])) {
          st.add(A[r]);
        }
 
        // Increment count of A[r]
        if (mp.containsKey(A[r]))
          mp.put(A[r], mp.get(A[r]) + 1);
        else
          mp.put(A[r], 1);
 
        // Increment r by 1
        r++;
 
        // If st.size() is K
        if (st.size() == K)
          cntSub++;
      }
 
      // Iterate while l < r
      // and st.size() > K
      while (l < r && st.size() > K) {
 
        // Increment cntSub by 1
        cntSub++;
 
        // Decrement cntSub by 1
        if (mp.containsKey(A[l]))
          mp.put(A[l], mp.get(A[l]) - 1);
 
        // If mp[A[l]] = 1
        if (mp.get(A[l]) == 1) {
          st.remove(A[l]);
        }
 
        // Increment l by 1
        l++;
      }
    }
 
    // Iterate while l < n  and
    // st.size() == K
    while (l < n && st.size() == K) {
 
      // Increment cntSub by 1
      cntSub++;
      if (mp.containsKey(A[l]))
        mp.put(A[l], mp.get(A[l]) - 1);
 
      // If Mp[A[l]] is equal to 1
      if (mp.get(A[l]) == 1) {
        st.remove(A[l]);
      }
 
      // Increment l by 1
      l++;
    }
 
    // Return cntSub
    return cntSub;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int[] arr = { 1, 1, 1, 2, 2 };
    int K = 1;
    int N = arr.length;
 
    System.out.println(cntSubarrays(arr, K, N));
  }
}
 
// This code is contributed by ukasp.


Python3




# Python3 program for the above approach
 
# Function to count the subarrays with
# exactly K elements occurring twice
def cntSubarrays(A, K, n):
     
    # Stores the count of subarrays
    # having exactly K elements
    # occurring at least twice
    cntSub = 0
 
    # Stores the count of
    # integers in the subarray
    mp = {}
 
    # Stores the indices of left
    # boundary and right boundary
    l = 0
    r = 0
 
    # Store the elements which occurs
    # atleast twice between [l, r]
    st = set()
 
    # Iterate while r < n
    while (r < n):
         
        # Iterate while r < n
        # and size of st <= K
        while (r < n and len(st) <= K):
             
            # If mp[A[r]] >= 1
            if (A[r] in mp):
                st.add(A[r])
 
            # Increment count of A[r]
            if (A[r] in mp):
                mp[A[r]] += 1
            else:
                mp[A[r]] = 1
 
            # Increment r by 1
            r += 1
 
            # If st.size() is K
            if (len(st) == K):
                cntSub += 1
 
        # Iterate while l < r
        # and st.size() > K
        while (l < r and len(st) > K):
             
            # Increment cntSub by 1
            cntSub += 1
 
            # Decrement cntSub by 1
            if (A[l] in mp):
                mp[A[l]] -= 1
            else:
                mp[A[l]] = 1
  
            # If mp[A[l]] = 1
            if (mp[A[l]] == 1):
                st.remove(A[l])
 
            # Increment l by 1
            l += 1
 
    # Iterate while l < n  and
    # st.size() == K
    while (l < n and len(st) == K):
         
        # Increment cntSub by 1
        cntSub += 1
 
        mp[A[l]] -= 1
 
        # If Mp[A[l]] is equal to 1
        if (mp[A[l]] == 1):
            st.remove(A[l])
 
        # Increment l by 1
        l += 1
 
    # Return cntSub
    return cntSub
 
# Driver Code
if __name__ == '__main__':
     
    arr =  [1, 1, 1, 2, 2]
    K = 1
    N = len(arr)
     
    print(cntSubarrays(arr, K, N))
 
# This code is contributed by ipg2016107


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
  // Function to count the subarrays with
  // exactly K elements occurring twice
  static int cntSubarrays(int []A, int K, int n)
  {
     
    // Stores the count of subarrays
    // having exactly K elements
    // occurring at least twice
    int cntSub = 0;
 
    // Stores the count of
    // integers in the subarray
    Dictionary<int,int> mp = new Dictionary<int,int>();
 
    // Stores the indices of left
    // boundary and right boundary
    int l = 0, r = 0;
 
    // Store the elements which occurs
    // atleast twice between [l, r]
    HashSet<int> st = new HashSet<int>();
 
    // Iterate while r < n
    while (r < n) {
 
      // Iterate while r < n
      // and size of st <= K
      while (r < n && st.Count <= K) {
 
        // If mp[A[r]] >= 1
        if (mp.ContainsKey(A[r])) {
          st.Add(A[r]);
        }
 
        // Increment count of A[r]
        if (mp.ContainsKey(A[r]))
          mp[A[r]]++;
        else
          mp[A[r]] = 1;
 
        // Increment r by 1
        r++;
 
        // If st.size() is K
        if (st.Count == K)
          cntSub++;
      }
 
      // Iterate while l < r
      // and st.size() > K
      while (l < r && st.Count > K) {
 
        // Increment cntSub by 1
        cntSub++;
 
        // Decrement cntSub by 1
        if (mp.ContainsKey(A[l]))
          mp[A[l]]--;
 
        // If mp[A[l]] = 1
        if (mp[A[l]] == 1) {
          st.Remove(A[l]);
        }
 
        // Increment l by 1
        l++;
      }
    }
 
    // Iterate while l < n  and
    // st.size() == K
    while (l < n && st.Count == K) {
 
      // Increment cntSub by 1
      cntSub++;
      if (mp.ContainsKey(A[l]))
        mp[A[l]]--;
 
      // If Mp[A[l]] is equal to 1
      if (mp[A[l]] == 1) {
        st.Remove(A[l]);
      }
 
      // Increment l by 1
      l++;
    }
 
    // Return cntSub
    return cntSub;
  }
 
  // Driver Code
  public static void Main()
  {
    int []arr = { 1, 1, 1, 2, 2 };
    int K = 1;
    int N = arr.Length;
 
    Console.WriteLine(cntSubarrays(arr, K, N));
  }
}
 
// This code is contributed by ipg2016107.


Javascript




<script>
 
// JavaScript program for the above approach
 
// Function to count the subarrays with
// exactly K elements occurring twice
function cntSubarrays(A,K,n)
{
    // Stores the count of subarrays
    // having exactly K elements
    // occurring at least twice
    let cntSub = 0;
  
    // Stores the count of
    // integers in the subarray
    let mp = new Map();
  
    // Stores the indices of left
    // boundary and right boundary
    let l = 0, r = 0;
  
    // Store the elements which occurs
    // atleast twice between [l, r]
    let st = new Set();
  
    // Iterate while r < n
    while (r < n) {
  
      // Iterate while r < n
      // and size of st <= K
      while (r < n && st.size <= K) {
  
        // If mp[A[r]] >= 1
        if (mp.has(A[r])) {
          st.add(A[r]);
        }
  
        // Increment count of A[r]
        if (mp.has(A[r]))
          mp.set(A[r], mp.get(A[r]) + 1);
        else
          mp.set(A[r], 1);
  
        // Increment r by 1
        r++;
  
        // If st.size() is K
        if (st.size == K)
          cntSub++;
      }
  
      // Iterate while l < r
      // and st.size() > K
      while (l < r && st.size > K) {
  
        // Increment cntSub by 1
        cntSub++;
  
        // Decrement cntSub by 1
        if (mp.has(A[l]))
          mp.set(A[l], mp.get(A[l]) - 1);
  
        // If mp[A[l]] = 1
        if (mp.get(A[l]) == 1) {
          st.delete(A[l]);
        }
  
        // Increment l by 1
        l++;
      }
    }
  
    // Iterate while l < n  and
    // st.size() == K
    while (l < n && st.size == K) {
  
      // Increment cntSub by 1
      cntSub++;
      if (mp.has(A[l]))
        mp.set(A[l], mp.get(A[l]) - 1);
  
      // If Mp[A[l]] is equal to 1
      if (mp.get(A[l]) == 1) {
        st.delete(A[l]);
      }
  
      // Increment l by 1
      l++;
    }
  
    // Return cntSub
    return cntSub;
}
 
 // Driver Code
let arr=[1, 1, 1, 2, 2 ];
let K = 1;
let N = arr.length;
document.write(cntSubarrays(arr, K, N));
 
 
// This code is contributed by avanitrachhadiya2155
 
</script>


Output: 

7

 

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



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads