Open In App

Shortest subarray to be removed to make all Array elements unique

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] containing N elements, the task is to remove a subarray of minimum possible length from the given array such that all remaining elements are distinct. Print the minimum possible length of the subarray.
Examples:

Input: N = 5, arr[] = {1, 2, 1, 2, 3} 
Output:
Explanation: 
Remove the sub array {2, 1} to make the elements distinct. 
Input: N = 5, arr[] = {1, 2, 3, 4, 5} 
Output:
Explanation: 
Elements are already distinct.

Naive Approach: The naive approach for this problem is to simply check for all the possible subarrays and find the length of the smallest subarray after removal of which all the elements in the array become distinct. 
Time complexity: O(N3) 
Efficient Approach:

  • Let ans be the length of the minimum subarray that on removing from the given array, makes the elements of the array unique.
  • We can easily observe that if all array elements become distinct after removing a subarray of length ans, then this condition is also true for all values greater than ans.
  • This means that the solution for this problem is a monotonically increasing function and we can apply binary search on the answer.
  • Now, for a particular length K of subarray, we can check if elements of prefix and suffix of all sub arrays of length K are distinct or not.
  • We can do this by using a sliding window technique.
  • Use a hash map to store the frequencies of elements in prefix and suffix, on moving the window forward, increment frequency of the last element of prefix and decrement frequency of the first element of suffix.

Below is the implementation of the above approach:

C++




// C++ program to make array elements
// distinct by removing at most
// one subarray of minimum length
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to check if elements of
// Prefix and suffix of each sub array
// of size K are distinct or not
bool check(int a[], int n, int k)
{
    // Hash map to store frequencies of
    // elements of prefix and suffix
    map<int, int> m;
 
    // Variable to store number of
    // occurrences of an element other
    // than one
    int extra = 0;
 
    // Adding frequency of elements of suffix
    // to hash for subarray starting from first
    // index
    // There is no prefix for this sub array
    for (int i = k; i < n; i++)
        m[a[i]]++;
 
    // Counting extra elements in current Hash
    // map
    for (auto x : m)
        extra += x.second - 1;
 
    // If there are no extra elements return
    // true
    if (extra == 0)
        return true;
 
    // Check for remaining sub arrays
 
    for (int i = 1; i + k - 1 < n; i++) {
 
        // First element of suffix is now
        // part of subarray which is being
        // removed so, check for extra elements
        if (m[a[i + k - 1]] > 1)
            extra--;
 
        // Decrement frequency of first
        // element of the suffix
        m[a[i + k - 1]]--;
 
        // Increment frequency of last
        // element of the prefix
        m[a[i - 1]]++;
 
        // Check for extra elements
        if (m[a[i - 1]] > 1)
            extra++;
 
        // If there are no extra elements
        // return true
        if (extra == 0)
            return true;
    }
 
    return false;
}
 
// Function for calculating minimum
// length of the subarray, which on
// removing make all elements distinct
int minlength(int a[], int n)
{
    // Possible range of length of subarray
    int lo = 0, hi = n + 1;
 
    int ans = 0;
 
    // Binary search to find minimum ans
    while (lo < hi) {
 
        int mid = (lo + hi) / 2;
 
        if (check(a, n, mid)) {
            ans = mid;
            hi = mid;
        }
        else
            lo = mid + 1;
    }
 
    return ans;
}
 
// Driver code
int main()
{
    int a[5] = { 1, 2, 1, 2, 3 };
 
    int n = sizeof(a) / sizeof(int);
 
    cout << minlength(a, n);
}


Java




// Java program to make array elements
// pairwise distinct by removing at most
// one subarray of minimum length
import java.util.*;
import java.lang.*;
 
class GFG{
     
// Function to check if elements of
// Prefix and suffix of each sub array
// of size K are pairwise distinct or not
static boolean check(int a[], int n, int k)
{
     
    // Hash map to store frequencies of
    // elements of prefix and suffix
    Map<Integer, Integer> m = new HashMap<>();
     
    // Variable to store number of
    // occurrences of an element other
    // than one
    int extra = 0;
     
    // Adding frequency of elements of suffix
    // to hash for subarray starting from first
    // index
    // There is no prefix for this sub array
    for(int i = k; i < n; i++)
        m.put(a[i], m.getOrDefault(a[i], 0) + 1);
     
    // Counting extra elements in current Hash
    // map
    for(Integer x : m.values())
        extra += x - 1;
     
    // If there are no extra elements return
    // true
    if (extra == 0)
        return true;
     
    // Check for remaining sub arrays
    for(int i = 1; i + k - 1 < n; i++)
    {
         
        // First element of suffix is now
        // part of subarray which is being
        // removed so, check for extra elements
        if (m.get(a[i + k - 1]) > 1)
            extra--;
         
        // Decrement frequency of first
        // element of the suffix
        m.put(a[i + k - 1],
        m.get(a[i + k - 1]) - 1);
         
        // Increment frequency of last
        // element of the prefix
        m.put(a[i - 1], m.get(a[i - 1]) + 1);
         
        // Check for extra elements
        if (m.get(a[i - 1]) > 1)
            extra++;
         
        // If there are no extra elements
        // return true
        if (extra == 0)
            return true;
    }
    return false;
}
     
// Function for calculating minimum
// length of the subarray, which on
// removing make all elements pairwise
// distinct
static int minlength(int a[], int n)
{
     
    // Possible range of length of subarray
    int lo = 0, hi = n + 1;
     
    int ans = 0;
     
    // Binary search to find minimum ans
    while (lo < hi)
    {
        int mid = (lo + hi) / 2;
         
        if (check(a, n, mid))
        {
            ans = mid;
            hi = mid;
        }
        else
            lo = mid + 1;
    }
    return ans;
}
 
// Driver Code
public static void main (String[] args)
{
    int a[] = { 1, 2, 1, 2, 3 };
     
    int n = a.length;
     
    System.out.println(minlength(a, n));
}
}
 
// This code is contributed by offbeat


Python3




# Python3 program to make array elements
# pairwise distinct by removing at most
# one subarray of minimum length
from collections import defaultdict
 
# Function to check if elements of
# Prefix and suffix of each sub array
# of size K are pairwise distinct or not
def check(a, n, k):
 
    # Hash map to store frequencies of
    # elements of prefix and suffix
    m = defaultdict(int)
 
    # Variable to store number of
    # occurrences of an element other
    # than one
    extra = 0
 
    # Adding frequency of elements of suffix
    # to hash for subarray starting from first
    # index
    # There is no prefix for this sub array
    for i in range(k, n):
        m[a[i]] += 1
 
    # Counting extra elements in current Hash
    # map
    for x in m:
        extra += m[x] - 1
 
    # If there are no extra elements return
    # true
    if (extra == 0):
        return True
 
    # Check for remaining sub arrays
    for i in range(1, i + k - 1 < n):
 
        # First element of suffix is now
        # part of subarray which is being
        # removed so, check for extra elements
        if (m[a[i + k - 1]] > 1):
            extra -= 1
 
        # Decrement frequency of first
        # element of the suffix
        m[a[i + k - 1]] -= 1
 
        # Increment frequency of last
        # element of the prefix
        m[a[i - 1]] += 1
 
        # Check for extra elements
        if (m[a[i - 1]] > 1):
            extra += 1
 
        # If there are no extra elements
        # return true
        if (extra == 0):
            return True
     
    return False
 
# Function for calculating minimum
# length of the subarray, which on
# removing make all elements pairwise
# distinct
def minlength(a, n):
 
    # Possible range of length of subarray
    lo = 0
    hi = n + 1
 
    ans = 0
 
    # Binary search to find minimum ans
    while (lo < hi):
        mid = (lo + hi) // 2
 
        if (check(a, n, mid)):
            ans = mid
            hi = mid
        else:
            lo = mid + 1
 
    return ans
 
# Driver code
if __name__ == "__main__":
 
    a = [ 1, 2, 1, 2, 3 ]
    n = len(a)
 
    print(minlength(a, n))
 
# This code is contributed by chitranayal


C#




// C# program to make array elements
// pairwise distinct by removing at most
// one subarray of minimum length
using System;
using System.Collections.Generic;
 
class GFG{
     
// Function to check if elements of
// Prefix and suffix of each sub array
// of size K are pairwise distinct or not
static bool check(int []a, int n, int k)
{
     
    // Hash map to store frequencies of
    // elements of prefix and suffix
    Dictionary<int,
               int> m = new Dictionary<int,
                                       int>();
     
    // Variable to store number of
    // occurrences of an element other
    // than one
    int extra = 0;
     
    // Adding frequency of elements of suffix
    // to hash for subarray starting from first
    // index
    // There is no prefix for this sub array
    for(int i = k; i < n; i++)
        if(m.ContainsKey(a[i]))
            m[a[i]] = m[a[i]] + 1;
        else
            m.Add(a[i], 1);
     
    // Counting extra elements in current Hash
    // map
    foreach(int x in m.Keys)
        extra += m[x] - 1;
     
    // If there are no extra elements return
    // true
    if (extra == 0)
        return true;
     
    // Check for remaining sub arrays
    for(int i = 1; i + k - 1 < n; i++)
    {
         
        // First element of suffix is now
        // part of subarray which is being
        // removed so, check for extra elements
        if (m[a[i + k - 1]] > 1)
            extra--;
         
        // Decrement frequency of first
        // element of the suffix
        m[a[i + k - 1]] = m[a[i + k - 1]] - 1;
         
        // Increment frequency of last
        // element of the prefix
        m[a[i - 1]] = m[a[i - 1]] + 1;
         
        // Check for extra elements
        if (m[a[i - 1]] > 1)
            extra++;
         
        // If there are no extra elements
        // return true
        if (extra == 0)
            return true;
    }
    return false;
}
     
// Function for calculating minimum
// length of the subarray, which on
// removing make all elements pairwise
// distinct
static int minlength(int []a, int n)
{
     
    // Possible range of length of subarray
    int lo = 0, hi = n + 1;
     
    int ans = 0;
     
    // Binary search to find minimum ans
    while (lo < hi)
    {
        int mid = (lo + hi) / 2;
         
        if (check(a, n, mid))
        {
            ans = mid;
            hi = mid;
        }
        else
            lo = mid + 1;
    }
    return ans;
}
 
// Driver Code
public static void Main(String[] args)
{
    int []a = { 1, 2, 1, 2, 3 };
    int n = a.Length;
     
    Console.WriteLine(minlength(a, n));
}
}
 
// This code is contributed by Amit Katiyar


Javascript




<script>
// Javascript program to make array elements
// pairwise distinct by removing at most
// one subarray of minimum length
 
// Function to check if elements of
// Prefix and suffix of each sub array
// of size K are pairwise distinct or not
function check(a, n, k)
{
 
    // Hash map to store frequencies of
    // elements of prefix and suffix
    let m = new Map();
       
    // Variable to store number of
    // occurrences of an element other
    // than one
    let extra = 0;
       
    // Adding frequency of elements of suffix
    // to hash for subarray starting from first
    // index
    // There is no prefix for this sub array
    for(let i = k; i < n; i++)
        m.set(a[i], m.get(a[i])==null? 1 :m.get(a[i])+ 1);
       
    // Counting extra elements in current Hash
    // map
    for(let x of m.values())
        extra += x - 1;
       
    // If there are no extra elements return
    // true
    if (extra == 0)
        return true;
       
    // Check for remaining sub arrays
    for(let i = 1; i + k - 1 < n; i++)
    {
           
        // First element of suffix is now
        // part of subarray which is being
        // removed so, check for extra elements
        if (m.get(a[i + k - 1]) > 1)
            extra--;
           
        // Decrement frequency of first
        // element of the suffix
        m.set(a[i + k - 1],
        m.get(a[i + k - 1]) - 1);
           
        // Increment frequency of last
        // element of the prefix
        m.set(a[i - 1], m.get(a[i - 1]) + 1);
           
        // Check for extra elements
        if (m.get(a[i - 1]) > 1)
            extra++;
           
        // If there are no extra elements
        // return true
        if (extra == 0)
            return true;
    }
    return false;
}
 
// Function for calculating minimum
// length of the subarray, which on
// removing make all elements pairwise
// distinct
function minlength(a,n)
{
    // Possible range of length of subarray
    let lo = 0, hi = n + 1;
       
    let ans = 0;
       
    // Binary search to find minimum ans
    while (lo < hi)
    {
        let mid = Math.floor((lo + hi) / 2);
           
        if (check(a, n, mid))
        {
            ans = mid;
            hi = mid;
        }
        else
            lo = mid + 1;
    }
    return ans;
}
 
// Driver Code
let a = [1, 2, 1, 2, 3 ];
let n = a.length;
document.write(minlength(a, n));
 
// This code is contributed by avanitrachhadiya2155
</script>


Output: 

2

Time Complexity: O(N * log(N)), where N is the size of the array, This is because the function “check” runs in O(n) time, and the function “minlength” performs a binary search on the length of the subarray, which takes O(log n) time.

Auxiliary Space: O(N), as it uses a hash map to store the frequencies of elements in each subarray, which can have up to n elements.
 



Last Updated : 29 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads