Count subarrays having exactly K elements occurring at least twice

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}. Frequency of 1 is 2.
- {1, 1, 1}. Frequency of 1 is 3.
- {1, 1, 1, 2}. Frequency of 1 is 3.
- {1, 1}. Frequency of 1 is 2.
- {1, 1, 2}. Frequency of 1 is 2.
- {1, 2, 2}. Frequency of 2 is 2.
- {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.
- Iterate while r is less than N and the size of the set is at most K:
- 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 twiceint 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 Codeint 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 approachimport 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 twicedef 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 Codeif __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 approachusing 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 twicefunction 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 Codelet 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> |
7
Â
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



