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

📅  最后修改于: 2021-05-17 18:42:02             🧑  作者: Mango

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

幼稚的方法:针对此问题的幼稚的方法是简单地检查所有可能的子数组,并在删除数组中的所有元素成对区分后找到最小子数组的长度。

时间复杂度: O(N 3 )

高效方法:

  • ans为从给定数组中删除时使数组元素唯一的最小子数组的长度。
  • 我们可以很容易地观察到,如果所有数组元素在删除长度为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


输出:
2

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