Find minimum subarray length to reduce frequency
Given an array arr[] of length N and a positive integer k, the task is to find the minimum length of the subarray that needs to be removed from the given array such that the frequency of the remaining elements in the array is less than or equal to k.
Examples:
Input: n = 4, arr[] = {3, 1, 3, 6}, k = 1
Output: 1
Explanation: We can see that only 3 is having frequency 2 that is greater than k. So we can remove the 3 at the start of the array to that frequency of all elements become less than or equal to k. Thus the minimum length of the subarray to be removed is 1.Input: n = 6, arr[] = {1, 2, 3, 3, 2, 1}, k = 1
Output: 3
Explanation: We Can remove the subarray {1, 2, 3} which is the minimum possible length subarray after being removed making the frequency of remaining elements less than or equal to k.
Approach: This can be solved with the following idea:
This problem can be solved using Binary Search and Sliding Window Technique.
Below are the steps involved in the implementation of the code:
- Create a Hash Table to store the frequency of the elements of the given array.
- Create a variable cnt to store the count of numbers to be removed for satisfying the condition that the frequency of remaining elements after removing the subarray becomes less than or equal to k.
- Store the frequency of the array elements in the Hash table.
- If the frequency of an element becomes greater than k then increment cnt.
- Now the subarray size lies in the range [0, n] where n is the array length. So we can apply binary search to it.
- Initialize the answer as n.
- Find the mid element on every iteration of binary search and create a window of size mid and check if it is possible that removing this window size from the array can make cnt equal to zero.
- If it is possible update the answer as a minimum of answer and mid and now reduce the search space to [left, mid-1] to find if a smaller length is possible.
- If it is not possible then reduce the search space to [mid+1, r] to find for larger length than mid.
- After the end of the binary search, we will get the required answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h> using namespace std; // Function to find minimum length // needed to be removed int minLength( int n, int k, vector< int >& arr) { // Map to keep the count of // Frequency unordered_map< int , int > f; int cnt = 0; for ( int i = 0; i < n; i++) { f[arr[i]]++; if (f[arr[i]] > k) cnt++; } int l = 0, r = n; int ans = n; // Binary search while (l <= r) { int mid = l + (r - l) / 2; for ( int i = 0; i < mid; i++) { if (f[arr[i]] > k) cnt--; f[arr[i]]--; } if (cnt == 0) { ans = min(ans, mid); r = mid - 1; for ( int i = 0; i < mid; i++) { f[arr[i]]++; if (f[arr[i]] > k) cnt++; } continue ; } bool flag = false ; // If particular length is possible for ( int i = mid; i < n; i++) { if (f[arr[i - mid]] >= k) cnt++; f[arr[i - mid]]++; if (f[arr[i]] > k) cnt--; f[arr[i]]--; if (cnt == 0) { for ( int j = i - mid + 1; j <= i; j++) { f[arr[j]]++; if (f[arr[j]] > k) cnt++; } flag = true ; break ; } } if (flag) { ans = min(ans, mid); r = mid - 1; } else { l = mid + 1; for ( int i = n - mid; i < n; i++) { f[arr[i]]++; if (f[arr[i]] > k) cnt++; } } } // Return the ans return ans; } // Driver code int main() { int n = 4; int k = 1; vector< int > arr = { 3, 1, 2, 3 }; // Function call cout << minLength(n, k, arr); return 0; } |
Java
import java.util.HashMap; import java.util.Map; import java.util.Vector; class GFG { // Function to find minimum length // needed to be removed static int minLength( int n, int k, Vector<Integer> arr) { // Map to keep the count of Frequency Map<Integer, Integer> f = new HashMap<>(); int cnt = 0 ; for ( int i = 0 ; i < n; i++) { f.put(arr.get(i), f.getOrDefault(arr.get(i), 0 ) + 1 ); if (f.get(arr.get(i)) > k) cnt++; } int l = 0 , r = n; int ans = n; // Binary search while (l <= r) { int mid = l + (r - l) / 2 ; for ( int i = 0 ; i < mid; i++) { if (f.get(arr.get(i)) > k) cnt--; f.put(arr.get(i), f.get(arr.get(i)) - 1 ); } if (cnt == 0 ) { ans = Math.min(ans, mid); r = mid - 1 ; for ( int i = 0 ; i < mid; i++) { f.put(arr.get(i), f.get(arr.get(i)) + 1 ); if (f.get(arr.get(i)) > k) cnt++; } continue ; } boolean flag = false ; // If particular length is possible for ( int i = mid; i < n; i++) { if (f.get(arr.get(i - mid)) >= k) cnt++; f.put(arr.get(i - mid), f.get(arr.get(i - mid)) + 1 ); if (f.get(arr.get(i)) > k) cnt--; f.put(arr.get(i), f.get(arr.get(i)) - 1 ); if (cnt == 0 ) { for ( int j = i - mid + 1 ; j <= i; j++) { f.put(arr.get(j), f.get(arr.get(j)) + 1 ); if (f.get(arr.get(j)) > k) cnt++; } flag = true ; break ; } } if (flag) { ans = Math.min(ans, mid); r = mid - 1 ; } else { l = mid + 1 ; for ( int i = n - mid; i < n; i++) { f.put(arr.get(i), f.get(arr.get(i)) + 1 ); if (f.get(arr.get(i)) > k) cnt++; } } } // Return the ans return ans; } // Nikunj Sonigara public static void main(String[] args) { int n = 4 ; int k = 1 ; Vector<Integer> arr = new Vector<>( 4 ); arr.add( 3 ); arr.add( 1 ); arr.add( 2 ); arr.add( 3 ); // Function call System.out.println(minLength(n, k, arr)); } } |
Python3
# Python code for the above approach from typing import List from collections import defaultdict # Function to find minimum length needed to be removed def min_length(n: int , k: int , arr: List [ int ]) - > int : # Dictionary to keep the count of frequency f = defaultdict( int ) cnt = 0 for i in range (n): f[arr[i]] + = 1 if f[arr[i]] > k: cnt + = 1 l = 0 r = n ans = n # Binary search while l < = r: mid = l + (r - l) / / 2 for i in range (mid): if f[arr[i]] > k: cnt - = 1 f[arr[i]] - = 1 if cnt = = 0 : ans = min (ans, mid) r = mid - 1 for i in range (mid): f[arr[i]] + = 1 if f[arr[i]] > k: cnt + = 1 continue flag = False # If a particular length is possible for i in range (mid, n): if f[arr[i - mid]] > = k: cnt + = 1 f[arr[i - mid]] + = 1 if f[arr[i]] > k: cnt - = 1 f[arr[i]] - = 1 if cnt = = 0 : for j in range (i - mid + 1 , i + 1 ): f[arr[j]] + = 1 if f[arr[j]] > k: cnt + = 1 flag = True break if flag: ans = min (ans, mid) r = mid - 1 else : l = mid + 1 for i in range (n - mid, n): f[arr[i]] + = 1 if f[arr[i]] > k: cnt + = 1 # Return the answer return ans # Driver code if __name__ = = "__main__" : n = 4 k = 1 arr = [ 3 , 1 , 2 , 3 ] # Function call print (min_length(n, k, arr)) |
C#
// c# code for the above approach using System; using System.Collections.Generic; class GFG { // Function to find minimum length // needed to be removed static int MinLength( int n, int k, List< int > arr) { // Dictionary to keep the count of Frequency Dictionary< int , int > f = new Dictionary< int , int >(); int cnt = 0; for ( int i = 0; i < n; i++) { if (f.ContainsKey(arr[i])) f[arr[i]]++; else f[arr[i]] = 1; if (f[arr[i]] > k) cnt++; } int l = 0, r = n; int ans = n; // Binary search while (l <= r) { int mid = l + (r - l) / 2; for ( int i = 0; i < mid; i++) { if (f[arr[i]] > k) cnt--; f[arr[i]]--; } if (cnt == 0) { ans = Math.Min(ans, mid); r = mid - 1; for ( int i = 0; i < mid; i++) { f[arr[i]]++; if (f[arr[i]] > k) cnt++; } continue ; } bool flag = false ; // If a particular length is possible for ( int i = mid; i < n; i++) { if (f[arr[i - mid]] >= k) cnt++; f[arr[i - mid]]++; if (f[arr[i]] > k) cnt--; f[arr[i]]--; if (cnt == 0) { for ( int j = i - mid + 1; j <= i; j++) { f[arr[j]]++; if (f[arr[j]] > k) cnt++; } flag = true ; break ; } } if (flag) { ans = Math.Min(ans, mid); r = mid - 1; } else { l = mid + 1; for ( int i = n - mid; i < n; i++) { f[arr[i]]++; if (f[arr[i]] > k) cnt++; } } } // Return the ans return ans; } // Nikunj Sonigara public static void Main( string [] args) { int n = 4; int k = 1; List< int > arr = new List< int > { 3, 1, 2, 3 }; // Function call Console.WriteLine(MinLength(n, k, arr)); } } |
Javascript
//JavaScript code function minLength(n, k, arr) { const f = new Map(); let cnt = 0; for (let i = 0; i < n; i++) { if (!f.has(arr[i])) { f.set(arr[i], 1); } else { f.set(arr[i], f.get(arr[i]) + 1); if (f.get(arr[i]) > k) { cnt++; } } } let l = 0, r = n; let ans = n; while (l <= r) { const mid = l + Math.floor((r - l) / 2); for (let i = 0; i < mid; i++) { if (f.get(arr[i]) > k) { cnt--; } f.set(arr[i], f.get(arr[i]) - 1); } if (cnt === 0) { ans = Math.min(ans, mid); r = mid - 1; for (let i = 0; i < mid; i++) { f.set(arr[i], f.get(arr[i]) + 1); if (f.get(arr[i]) > k) { cnt++; } } continue ; } let flag = false ; for (let i = mid; i < n; i++) { if (f.get(arr[i - mid]) >= k) { cnt++; } f.set(arr[i - mid], f.get(arr[i - mid]) + 1); if (f.get(arr[i]) > k) { cnt--; } f.set(arr[i], f.get(arr[i]) - 1); if (cnt === 0) { for (let j = i - mid + 1; j <= i; j++) { f.set(arr[j], f.get(arr[j]) + 1); if (f.get(arr[j]) > k) { cnt++; } } flag = true ; break ; } } if (flag) { ans = Math.min(ans, mid); r = mid - 1; } else { l = mid + 1; for (let i = n - mid; i < n; i++) { f.set(arr[i], f.get(arr[i]) + 1); if (f.get(arr[i]) > k) { cnt++; } } } } return ans; } // Driver code const n = 4; const k = 1; const arr = [3, 1, 2, 3]; // Function call console.log(minLength(n, k, arr)); //Contributed by Aditi Tyagi |
1
Time Complexity: O(N*logN)
Auxiliary Space: O(N)