给定一个字符串,您需要打印可能的最长子字符串,该子字符串恰好包含 M 个唯一字符。如果有多个最长可能长度的子字符串,则打印其中的任何一个。
例子:
"aabbcc", k = 1
Max substring can be any one from {"aa" , "bb" , "cc"}.
"aabbcc", k = 2
Max substring can be any one from {"aabb" , "bbcc"}.
"aabbcc", k = 3
There are substrings with exactly 3 unique characters
{"aabbcc" , "abbcc" , "aabbc" , "abbc" }
Max is "aabbcc" with length 6.
"aaabbb", k = 3
There are only two unique characters, thus show error message.
资料来源:谷歌面试问题。
方法一(蛮力)
如果字符串的长度为 n,则可以有 n*(n+1)/2 个可能的子字符串。一种简单的方法是生成所有子串并检查每个子串是否恰好有 k 个唯一字符。如果我们应用这种蛮力,则需要 O(n 2 ) 来生成所有子串,并且需要 O(n) 来检查每个子串。因此总体上它会变成 O(n 3 )。
我们可以通过创建哈希表并在生成子字符串时使用该哈希表检查唯一字符的数量来进一步改进此解决方案。因此它将提高到 O(n 2 )。
方法二(线性时间)
这个问题可以用 O(n) 解决。想法是维护一个窗口并向窗口添加元素,直到它包含小于或等于 k ,如果需要,在这样做时更新我们的结果。如果唯一元素超出窗口中的要求,则开始从左侧删除元素。
下面是上面的实现。这些实现假设输入字符串字母表仅包含 26 个字符(从“a”到“z”)。代码可以很容易地扩展到 256 个字符。
C++
// C++ program to find the longest substring with k unique
// characters in a given string
#include
#include
#define MAX_CHARS 26
using namespace std;
// This function calculates number of unique characters
// using a associative array count[]. Returns true if
// no. of characters are less than required else returns
// false.
bool isValid(int count[], int k)
{
int val = 0;
for (int i=0; i 0)
val++;
// Return true if k is greater than or equal to val
return (k >= val);
}
// Finds the maximum substring with exactly k unique chars
void kUniques(string s, int k)
{
int u = 0; // number of unique characters
int n = s.length();
// Associative array to store the count of characters
int count[MAX_CHARS];
memset(count, 0, sizeof(count));
// Traverse the string, Fills the associative array
// count[] and count number of unique characters
for (int i=0; i max_window_size)
{
max_window_size = curr_end-curr_start+1;
max_window_start = curr_start;
}
}
cout << "Max sustring is : "
<< s.substr(max_window_start, max_window_size)
<< " with length " << max_window_size << endl;
}
// Driver function
int main()
{
string s = "aabacbebebe";
int k = 3;
kUniques(s, k);
return 0;
}
Java
import java.util.Arrays;
// Java program to find the longest substring with k unique
// characters in a given string
class GFG {
final static int MAX_CHARS = 26;
// This function calculates number
// of unique characters
// using a associative array
// count[]. Returns true if
// no. of characters are less
// than required else returns
// false.
static boolean isValid(int count[],
int k)
{
int val = 0;
for (int i = 0; i < MAX_CHARS; i++)
{
if (count[i] > 0)
{
val++;
}
}
// Return true if k is greater
// than or equal to val
return (k >= val);
}
// Finds the maximum substring
// with exactly k unique chars
static void kUniques(String s, int k)
{
int u = 0;
int n = s.length();
// Associative array to store
// the count of characters
int count[] = new int[MAX_CHARS];
Arrays.fill(count, 0);
// Traverse the string, Fills
// the associative array
// count[] and count number
// of unique characters
for (int i = 0; i < n; i++)
{
if (count[s.charAt(i) - 'a'] == 0)
{
u++;
}
count[s.charAt(i) - 'a']++;
}
// If there are not enough
// unique characters, show
// an error message.
if (u < k) {
System.out.print("Not enough unique characters");
return;
}
// Otherwise take a window with
// first element in it.
// start and end variables.
int curr_start = 0, curr_end = 0;
// Also initialize values for
// result longest window
int max_window_size = 1;
int max_window_start = 0;
// Initialize associative
// array count[] with zero
Arrays.fill(count, 0);
// put the first character
count[s.charAt(0) - 'a']++;
// Start from the second character and add
// characters in window according to above
// explanation
for (int i = 1; i < n; i++) {
// Add the character 's[i]'
// to current window
count[s.charAt(i) - 'a']++;
curr_end++;
// If there are more than k
// unique characters in
// current window, remove from left side
while (!isValid(count, k)) {
count[s.charAt(curr_start) - 'a']--;
curr_start++;
}
// Update the max window size if required
if (curr_end - curr_start + 1 > max_window_size)
{
max_window_size = curr_end - curr_start + 1;
max_window_start = curr_start;
}
}
System.out.println("Max sustring is : "
+ s.substring(max_window_start,
max_window_start + max_window_size)
+ " with length " + max_window_size);
}
// Driver Code
static public void main(String[] args) {
String s = "aabacbebebe";
int k = 3;
kUniques(s, k);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python program to find the longest substring with k unique
# characters in a given string
MAX_CHARS = 26
# This function calculates number of unique characters
# using a associative array count[]. Returns true if
# no. of characters are less than required else returns
# false.
def isValid(count, k):
val = 0
for i in range(MAX_CHARS):
if count[i] > 0:
val += 1
# Return true if k is greater than or equal to val
return (k >= val)
# Finds the maximum substring with exactly k unique characters
def kUniques(s, k):
u = 0 # number of unique characters
n = len(s)
# Associative array to store the count
count = [0] * MAX_CHARS
# Tranverse the string, fills the associative array
# count[] and count number of unique characters
for i in range(n):
if count[ord(s[i])-ord('a')] == 0:
u += 1
count[ord(s[i])-ord('a')] += 1
# If there are not enough unique characters, show
# an error message.
if u < k:
print ("Not enough unique characters")
return
# Otherwise take a window with first element in it.
# start and end variables.
curr_start = 0
curr_end = 0
# Also initialize values for result longest window
max_window_size = 1
max_window_start = 0
# Initialize associative array count[] with zero
count = [0] * len(count)
count[ord(s[0])-ord('a')] += 1 # put the first character
# Start from the second character and add
# characters in window according to above
# explanation
for i in range(1,n):
# Add the character 's[i]' to current window
count[ord(s[i])-ord('a')] += 1
curr_end+=1
# If there are more than k unique characters in
# current window, remove from left side
while not isValid(count, k):
count[ord(s[curr_start])-ord('a')] -= 1
curr_start += 1
# Update the max window size if required
if curr_end-curr_start+1 > max_window_size:
max_window_size = curr_end-curr_start+1
max_window_start = curr_start
print ("Max substring is : " + s[max_window_start:max_window_start + max_window_size]
+ " with length " + str(max_window_size))
# Driver function
s = "aabacbebebe"
k = 3
kUniques(s, k)
# This code is contributed by BHAVYA JAIN
C#
// C# program to find the longest substring with k unique
// characters in a given string
using System;
public class GFG
{
static int MAX_CHARS = 26;
// This function calculates number
// of unique characters
// using a associative array
// count[]. Returns true if
// no. of characters are less
// than required else returns
// false.
static bool isValid(int[] count,
int k)
{
int val = 0;
for (int i = 0; i < MAX_CHARS; i++)
{
if (count[i] > 0)
{
val++;
}
}
// Return true if k is greater
// than or equal to val
return (k >= val);
}
// Finds the maximum substring
// with exactly k unique chars
static void kUniques(string s, int k)
{
int u = 0;
int n = s.Length;
// Associative array to store
// the count of characters
int[] count = new int[MAX_CHARS];
Array.Fill(count, 0);
// Traverse the string, Fills
// the associative array
// count[] and count number
// of unique characters
for (int i = 0; i < n; i++)
{
if (count[s[i] - 'a'] == 0)
{
u++;
}
count[s[i] - 'a']++;
}
// If there are not enough
// unique characters, show
// an error message.
if (u < k) {
Console.Write("Not enough unique characters");
return;
}
// Otherwise take a window with
// first element in it.
// start and end variables.
int curr_start = 0, curr_end = 0;
// Also initialize values for
// result longest window
int max_window_size = 1;
int max_window_start = 0;
// Initialize associative
// array count[] with zero
Array.Fill(count, 0);
// put the first character
count[s[0] - 'a']++;
// Start from the second character and add
// characters in window according to above
// explanation
for (int i = 1; i < n; i++)
{
// Add the character 's[i]'
// to current window
count[s[i] - 'a']++;
curr_end++;
// If there are more than k
// unique characters in
// current window, remove from left side
while (!isValid(count, k)) {
count[s[curr_start] - 'a']--;
curr_start++;
}
// Update the max window size if required
if (curr_end - curr_start + 1 > max_window_size)
{
max_window_size = curr_end - curr_start + 1;
max_window_start = curr_start;
}
}
Console.WriteLine("Max sustring is : "+
s.Substring(max_window_start, max_window_size) +
" with length " + max_window_size);
}
// Driver code
static public void Main (){
string s = "aabacbebebe";
int k = 3;
kUniques(s, k);
}
}
// This code is contributed by avanitrachhadiya2155
Javascript
输出:
Max sustring is : cbebebe with length 7
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。