给定一个包含N 个元素的数组arr[] ,任务是从给定的数组中删除一个最小可能长度的子数组,使得所有剩余的元素都是成对不同的。打印子数组的最小可能长度。
例子:
Input: N = 5, arr[] = {1, 2, 1, 2, 3}
Output: 2
Explanation:
Remove the sub array {2, 1} to make the elements distinct.
Input: N = 5, arr[] = {1, 2, 3, 4, 5}
Output: 0
Explanation:
Elements are already distinct.
朴素的方法:这个问题的朴素的方法是简单地检查所有可能的子数组,并找到最小子数组的长度,删除后数组中的所有元素都变得两两不同。
时间复杂度: 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 现场工作专业课程和学生竞争性编程现场课程。