给定一个由 n 个整数和一个整数 k 组成的数组。我们需要在数组 [l, r] 中找到最小范围(l 和 r 都包括在内),使得恰好有 k 个不同的数字。
例子:
Input : arr[] = { 1, 1, 2, 2, 3, 3, 4, 5}
k = 3
Output : 5 7
Input : arr[] = { 1, 2, 2, 3}
k = 2
Output : 0 1
一个简单的解决方案是使用两个嵌套循环。外环用于选取起点,内环用于选取终点。对于每一对起点,我们计算其中的不同元素,如果当前窗口较小,则更新结果。我们使用散列来计算范围内的不同元素。
C++
// C++ program to find minimum range that
// contains exactly k distinct numbers.
#include
using namespace std;
// Prints the minimum range that contains exactly
// k distinct numbers.
void minRange(int arr[], int n, int k)
{
int l = 0, r = n;
// Consider every element as starting
// point.
for (int i = 0; i < n; i++) {
// Find the smallest window starting
// with arr[i] and containing exactly
// k distinct elements.
unordered_set s;
int j;
for (j = i; j < n; j++) {
s.insert(arr[j]);
if (s.size() == k) {
if ((j - i) < (r - l)) {
r = j;
l = i;
}
break;
}
}
// There are less than k distinct elements
// now, so no need to continue.
if (j == n)
break;
}
// If there was no window with k distinct
// elements (k is greater than total distinct
// elements)
if (l == 0 && r == n)
cout << "Invalid k";
else
cout << l << " " << r;
}
// Driver code for above function.
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
int k = 3;
minRange(arr, n, k);
return 0;
}
Java
// Java program to find minimum
// range that contains exactly
// k distinct numbers.
import java.util.*;
class GFG
{
// Prints the minimum range
// that contains exactly k
// distinct numbers.
static void minRange(int arr[],
int n, int k)
{
int l = 0, r = n;
// Consider every element
// as starting point.
for (int i = 0; i < n; i++)
{
// Find the smallest window
// starting with arr[i] and
// containing exactly k
// distinct elements.
Set s = new HashSet();
int j;
for (j = i; j < n; j++)
{
s.add(arr[j]);
if (s.size() == k)
{
if ((j - i) < (r - l))
{
r = j;
l = i;
}
break;
}
}
// There are less than k
// distinct elements now,
// so no need to continue.
if (j == n)
break;
}
// If there was no window
// with k distinct elements
// (k is greater than total
// distinct elements)
if (l == 0 && r == n)
System.out.println("Invalid k");
else
System.out.println(l + " " + r);
}
// Driver code
public static void main(String args[])
{
int arr[] = { 1, 2, 3, 4, 5 };
int n = arr.length;
int k = 3;
minRange(arr, n, k);
}
}
// This code is contributed
// by Kirti_Mangal
Python 3
# Python 3 program to find minimum range
# that contains exactly k distinct numbers.
# Prints the minimum range that contains
# exactly k distinct numbers.
def minRange(arr, n, k):
l = 0
r = n
# Consider every element as
# starting point.
for i in range(n):
# Find the smallest window starting
# with arr[i] and containing exactly
# k distinct elements.
s = []
for j in range(i, n) :
s.append(arr[j])
if (len(s) == k):
if ((j - i) < (r - l)) :
r = j
l = i
break
# There are less than k distinct
# elements now, so no need to continue.
if (j == n):
break
# If there was no window with k distinct
# elements (k is greater than total
# distinct elements)
if (l == 0 and r == n):
print("Invalid k")
else:
print(l, r)
# Driver code
if __name__ == "__main__":
arr = [ 1, 2, 3, 4, 5 ]
n = len(arr)
k = 3
minRange(arr, n, k)
# This code is contributed
# by ChitraNayal
C#
// C# program to find minimum
// range that contains exactly
// k distinct numbers.
using System;
using System.Collections.Generic;
public class GFG
{
// Prints the minimum range
// that contains exactly k
// distinct numbers.
public static void minRange(int[] arr, int n, int k)
{
int l = 0, r = n;
// Consider every element
// as starting point.
for (int i = 0; i < n; i++)
{
// Find the smallest window
// starting with arr[i] and
// containing exactly k
// distinct elements.
ISet s = new HashSet();
int j;
for (j = i; j < n; j++)
{
s.Add(arr[j]);
if (s.Count == k)
{
if ((j - i) < (r - l))
{
r = j;
l = i;
}
break;
}
}
// There are less than k
// distinct elements now,
// so no need to continue.
if (j == n)
{
break;
}
}
// If there was no window
// with k distinct elements
// (k is greater than total
// distinct elements)
if (l == 0 && r == n)
{
Console.WriteLine("Invalid k");
}
else
{
Console.WriteLine(l + " " + r);
}
}
// Driver code
public static void Main(string[] args)
{
int[] arr = new int[] {1, 2, 3, 4, 5};
int n = arr.Length;
int k = 3;
minRange(arr, n, k);
}
}
// This code is contributed by Shrikant13
Javascript
C++
// C++ program to find minimum range that
// contains exactly k distinct numbers.
#include
using namespace std;
// prints the minimum range that contains exactly
// k distinct numbers.
void minRange(int arr[], int n, int k)
{
// Initially left and right side is -1 and -1,
// number of distinct elements are zero and
// range is n.
int l = 0, r = n;
int j = -1; // Initialize right side
map hm;
for (int i=0; i= (j - i)))
{
l = i;
r = j;
break;
}
}
// if number of distinct elements less
// than k, then break.
if (hm.size() < k)
break;
// if distinct elements equals to k then
// try to increment left side.
while (hm.size() == k)
{
if (hm[arr[i]] == 1)
hm.erase(arr[i]);
else
hm[arr[i]]--;
// increment left side.
i++;
// it is same as explained in above loop.
if (hm.size() == k && (r - l) >= (j - i))
{
l = i;
r = j;
}
}
if (hm[arr[i]] == 1)
hm.erase(arr[i]);
else
hm[arr[i]]--;
}
if (l == 0 && r == n)
cout << "Invalid k" << endl;
else
cout << l << " " << r << endl;
}
// Driver code for above function.
int main()
{
int arr[] = { 1, 1, 2, 2, 3, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
int k = 3;
minRange(arr, n, k);
return 0;
}
Java
// Java program to find minimum range that
// contains exactly k distinct numbers.
import java.util.*;
class GFG{
// Prints the minimum range that contains exactly
// k distinct numbers.
static void minRange(int arr[], int n, int k)
{
// Initially left and right side is -1 and -1,
// number of distinct elements are zero and
// range is n.
int l = 0, r = n;
// Initialize right side
int j = -1;
HashMap hm = new HashMap<>();
for(int i = 0; i < n; i++)
{
while (j < n)
{
// Increment right side.
j++;
// If number of distinct elements less
// than k.
if (j < n && hm.size() < k)
hm.put(arr[j],
hm.getOrDefault(arr[j], 0) + 1);
// If distinct elements are equal to k
// and length is less than previous length.
if (hm.size() == k &&
((r - l) >= (j - i)))
{
l = i;
r = j;
break;
}
}
// If number of distinct elements less
// than k, then break.
if (hm.size() < k)
break;
// If distinct elements equals to k then
// try to increment left side.
while (hm.size() == k)
{
if (hm.getOrDefault(arr[i], 0) == 1)
hm.remove(arr[i]);
else
hm.put(arr[i],
hm.getOrDefault(arr[i], 0) - 1);
// Increment left side.
i++;
// It is same as explained in above loop.
if (hm.size() == k &&
(r - l) >= (j - i))
{
l = i;
r = j;
}
}
if (hm.getOrDefault(arr[i], 0) == 1)
hm.remove(arr[i]);
else
hm.put(arr[i],
hm.getOrDefault(arr[i], 0) - 1);
}
if (l == 0 && r == n)
System.out.println("Invalid k");
else
System.out.println(l + " " + r);
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 1, 1, 2, 2, 3, 3, 4, 5 };
int n = arr.length;
int k = 3;
minRange(arr, n, k);
}
}
// This code is contributed by jrishabh99
Python3
# Python3 program to find the minimum range
# that contains exactly k distinct numbers.
from collections import defaultdict
# Prints the minimum range that contains
# exactly k distinct numbers.
def minRange(arr, n, k):
# Initially left and right side is -1
# and -1, number of distinct elements
# are zero and range is n.
l, r = 0, n
i = 0
j = -1 # Initialize right side
hm = defaultdict(lambda:0)
while i < n:
while j < n:
# increment right side.
j += 1
# if number of distinct elements less than k.
if len(hm) < k and j < n:
hm[arr[j]] += 1
# if distinct elements are equal to k
# and length is less than previous length.
if len(hm) == k and ((r - l) >= (j - i)):
l, r = i, j
break
# if number of distinct elements less
# than k, then break.
if len(hm) < k:
break
# if distinct elements equals to k then
# try to increment left side.
while len(hm) == k:
if hm[arr[i]] == 1:
del(hm[arr[i]])
else:
hm[arr[i]] -= 1
# increment left side.
i += 1
# it is same as explained in above loop.
if len(hm) == k and (r - l) >= (j - i):
l, r = i, j
if hm[arr[i]] == 1:
del(hm[arr[i]])
else:
hm[arr[i]] -= 1
i += 1
if l == 0 and r == n:
print("Invalid k")
else:
print(l, r)
# Driver code for above function.
if __name__ == "__main__":
arr = [1, 1, 2, 2, 3, 3, 4, 5]
n = len(arr)
k = 3
minRange(arr, n, k)
# This code is contributed by Rituraj Jain
C#
// C# program to find minimum
// range that contains exactly
// k distinct numbers.
using System;
using System.Collections.Generic;
class GFG{
// Prints the minimum
// range that contains exactly
// k distinct numbers.
static void minRange(int []arr,
int n, int k)
{
// Initially left and
// right side is -1 and -1,
// number of distinct
// elements are zero and
// range is n.
int l = 0, r = n;
// Initialize right side
int j = -1;
Dictionary hm = new Dictionary();
for(int i = 0; i < n; i++)
{
while (j < n)
{
// Increment right side.
j++;
// If number of distinct elements less
// than k.
if (j < n && hm.Count < k)
if(hm.ContainsKey(arr[j]))
hm[arr[j]] = hm[arr[j]] + 1;
else
hm.Add(arr[j], 1);
// If distinct elements are equal to k
// and length is less than previous length.
if (hm.Count == k &&
((r - l) >= (j - i)))
{
l = i;
r = j;
break;
}
}
// If number of distinct elements less
// than k, then break.
if (hm.Count < k)
break;
// If distinct elements equals to k then
// try to increment left side.
while (hm.Count == k)
{
if (hm.ContainsKey(arr[i]) &&
hm[arr[i]] == 1)
hm.Remove(arr[i]);
else
{
if(hm.ContainsKey(arr[i]))
hm[arr[i]] = hm[arr[i]] - 1;
}
// Increment left side.
i++;
// It is same as explained in above loop.
if (hm.Count == k &&
(r - l) >= (j - i))
{
l = i;
r = j;
}
}
if (hm.ContainsKey(arr[i]) &&
hm[arr[i]] == 1)
hm.Remove(arr[i]);
else
if(hm.ContainsKey(arr[i]))
hm[arr[i]] = hm[arr[i]] - 1;
}
if (l == 0 && r == n)
Console.WriteLine("Invalid k");
else
Console.WriteLine(l + " " + r);
}
// Driver code
public static void Main(String[] args)
{
int []arr = {1, 1, 2, 2,
3, 3, 4, 5};
int n = arr.Length;
int k = 3;
minRange(arr, n, k);
}
}
// This code is contributed by shikhasingrajput
Javascript
输出:
0 2
时间复杂度: O(n 2 )
对上述简单解决方案的优化。这个想法是在我们找到 k 个不同的元素后删除左侧的重复。
C++
// C++ program to find minimum range that
// contains exactly k distinct numbers.
#include
using namespace std;
// prints the minimum range that contains exactly
// k distinct numbers.
void minRange(int arr[], int n, int k)
{
// Initially left and right side is -1 and -1,
// number of distinct elements are zero and
// range is n.
int l = 0, r = n;
int j = -1; // Initialize right side
map hm;
for (int i=0; i= (j - i)))
{
l = i;
r = j;
break;
}
}
// if number of distinct elements less
// than k, then break.
if (hm.size() < k)
break;
// if distinct elements equals to k then
// try to increment left side.
while (hm.size() == k)
{
if (hm[arr[i]] == 1)
hm.erase(arr[i]);
else
hm[arr[i]]--;
// increment left side.
i++;
// it is same as explained in above loop.
if (hm.size() == k && (r - l) >= (j - i))
{
l = i;
r = j;
}
}
if (hm[arr[i]] == 1)
hm.erase(arr[i]);
else
hm[arr[i]]--;
}
if (l == 0 && r == n)
cout << "Invalid k" << endl;
else
cout << l << " " << r << endl;
}
// Driver code for above function.
int main()
{
int arr[] = { 1, 1, 2, 2, 3, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
int k = 3;
minRange(arr, n, k);
return 0;
}
Java
// Java program to find minimum range that
// contains exactly k distinct numbers.
import java.util.*;
class GFG{
// Prints the minimum range that contains exactly
// k distinct numbers.
static void minRange(int arr[], int n, int k)
{
// Initially left and right side is -1 and -1,
// number of distinct elements are zero and
// range is n.
int l = 0, r = n;
// Initialize right side
int j = -1;
HashMap hm = new HashMap<>();
for(int i = 0; i < n; i++)
{
while (j < n)
{
// Increment right side.
j++;
// If number of distinct elements less
// than k.
if (j < n && hm.size() < k)
hm.put(arr[j],
hm.getOrDefault(arr[j], 0) + 1);
// If distinct elements are equal to k
// and length is less than previous length.
if (hm.size() == k &&
((r - l) >= (j - i)))
{
l = i;
r = j;
break;
}
}
// If number of distinct elements less
// than k, then break.
if (hm.size() < k)
break;
// If distinct elements equals to k then
// try to increment left side.
while (hm.size() == k)
{
if (hm.getOrDefault(arr[i], 0) == 1)
hm.remove(arr[i]);
else
hm.put(arr[i],
hm.getOrDefault(arr[i], 0) - 1);
// Increment left side.
i++;
// It is same as explained in above loop.
if (hm.size() == k &&
(r - l) >= (j - i))
{
l = i;
r = j;
}
}
if (hm.getOrDefault(arr[i], 0) == 1)
hm.remove(arr[i]);
else
hm.put(arr[i],
hm.getOrDefault(arr[i], 0) - 1);
}
if (l == 0 && r == n)
System.out.println("Invalid k");
else
System.out.println(l + " " + r);
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 1, 1, 2, 2, 3, 3, 4, 5 };
int n = arr.length;
int k = 3;
minRange(arr, n, k);
}
}
// This code is contributed by jrishabh99
蟒蛇3
# Python3 program to find the minimum range
# that contains exactly k distinct numbers.
from collections import defaultdict
# Prints the minimum range that contains
# exactly k distinct numbers.
def minRange(arr, n, k):
# Initially left and right side is -1
# and -1, number of distinct elements
# are zero and range is n.
l, r = 0, n
i = 0
j = -1 # Initialize right side
hm = defaultdict(lambda:0)
while i < n:
while j < n:
# increment right side.
j += 1
# if number of distinct elements less than k.
if len(hm) < k and j < n:
hm[arr[j]] += 1
# if distinct elements are equal to k
# and length is less than previous length.
if len(hm) == k and ((r - l) >= (j - i)):
l, r = i, j
break
# if number of distinct elements less
# than k, then break.
if len(hm) < k:
break
# if distinct elements equals to k then
# try to increment left side.
while len(hm) == k:
if hm[arr[i]] == 1:
del(hm[arr[i]])
else:
hm[arr[i]] -= 1
# increment left side.
i += 1
# it is same as explained in above loop.
if len(hm) == k and (r - l) >= (j - i):
l, r = i, j
if hm[arr[i]] == 1:
del(hm[arr[i]])
else:
hm[arr[i]] -= 1
i += 1
if l == 0 and r == n:
print("Invalid k")
else:
print(l, r)
# Driver code for above function.
if __name__ == "__main__":
arr = [1, 1, 2, 2, 3, 3, 4, 5]
n = len(arr)
k = 3
minRange(arr, n, k)
# This code is contributed by Rituraj Jain
C#
// C# program to find minimum
// range that contains exactly
// k distinct numbers.
using System;
using System.Collections.Generic;
class GFG{
// Prints the minimum
// range that contains exactly
// k distinct numbers.
static void minRange(int []arr,
int n, int k)
{
// Initially left and
// right side is -1 and -1,
// number of distinct
// elements are zero and
// range is n.
int l = 0, r = n;
// Initialize right side
int j = -1;
Dictionary hm = new Dictionary();
for(int i = 0; i < n; i++)
{
while (j < n)
{
// Increment right side.
j++;
// If number of distinct elements less
// than k.
if (j < n && hm.Count < k)
if(hm.ContainsKey(arr[j]))
hm[arr[j]] = hm[arr[j]] + 1;
else
hm.Add(arr[j], 1);
// If distinct elements are equal to k
// and length is less than previous length.
if (hm.Count == k &&
((r - l) >= (j - i)))
{
l = i;
r = j;
break;
}
}
// If number of distinct elements less
// than k, then break.
if (hm.Count < k)
break;
// If distinct elements equals to k then
// try to increment left side.
while (hm.Count == k)
{
if (hm.ContainsKey(arr[i]) &&
hm[arr[i]] == 1)
hm.Remove(arr[i]);
else
{
if(hm.ContainsKey(arr[i]))
hm[arr[i]] = hm[arr[i]] - 1;
}
// Increment left side.
i++;
// It is same as explained in above loop.
if (hm.Count == k &&
(r - l) >= (j - i))
{
l = i;
r = j;
}
}
if (hm.ContainsKey(arr[i]) &&
hm[arr[i]] == 1)
hm.Remove(arr[i]);
else
if(hm.ContainsKey(arr[i]))
hm[arr[i]] = hm[arr[i]] - 1;
}
if (l == 0 && r == n)
Console.WriteLine("Invalid k");
else
Console.WriteLine(l + " " + r);
}
// Driver code
public static void Main(String[] args)
{
int []arr = {1, 1, 2, 2,
3, 3, 4, 5};
int n = arr.Length;
int k = 3;
minRange(arr, n, k);
}
}
// This code is contributed by shikhasingrajput
Javascript
输出:
5 7
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。