📌  相关文章
📜  要删除的最短子数组以使所有 Array 元素唯一

📅  最后修改于: 2021-10-28 01:42:42             🧑  作者: Mango

给定一个包含N 个元素的数组arr[] ,任务是从给定的数组中删除一个最小可能长度的子数组,使得所有剩余的元素都是成对不同的。打印子数组的最小可能长度。
例子:

朴素的方法:这个问题的朴素的方法是简单地检查所有可能的子数组,并找到最小子数组的长度,删除后数组中的所有元素都变得两两不同。
时间复杂度: O(N 3 )
有效的方法:

  • an为从给定数组中移除后使数组元素唯一的最小子数组的长度。
  • 我们可以很容易地观察到,如果删除长度为ans的子数组后所有数组元素变得不同,那么对于所有大于ans 的值,此条件也成立。
  • 这意味着这个问题的解决方案是一个单调递增的函数,我们可以对答案应用二分搜索。
  • 现在,对于特定长度K的子数组,我们可以检查所有长度为K 的子数组的前缀和后缀的元素是否成对不同。
  • 我们可以通过使用滑动窗口技术来做到这一点。
  • 使用哈希映射存储前缀和后缀中元素的频率,在向前移动窗口时,增加前缀最后一个元素的频率并减少后缀第一个元素的频率。

下面是上述方法的实现:

C++
// C++ program to make array elements
// pairwise distinct by removing at most
// one subarray of minimum length
 
#include 
using namespace std;
 
// Function to check if elements of
// Prefix and suffix of each sub array
// of size K are pairwise distinct or not
bool check(int a[], int n, int k)
{
    // Hash map to store frequencies of
    // elements of prefix and suffix
    map 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 pairwise
// 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 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 m = new Dictionary();
     
    // 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


输出:

2

时间复杂度: O(N * log(N)) ,其中 N 是数组的大小。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程