给定一个字符串str和一个整数K ,任务是打印具有恰好K个唯一字符的最长子字符串的长度。如果有一个以上可能的最长子串,则打印其中任何一个,如果没有这样的子串,则打印-1 。
例子:
Input: str = “aabacbebebe”, K = 3
Output: 7
“cbebebe” is the requried substring.
Input: str = “aabc”, K = 4
Output: -1
方法:本文讨论了一种解决此问题的方法。在本文中,将讨论基于二进制搜索的方法。将对至少具有K个唯一字符的子字符串的长度应用二进制搜索。假设我们尝试使用长度len并检查是否存在大小为len的子字符串,该子字符串至少包含k个唯一字符。如果可能,则尝试通过从该长度搜索到最大可能的长度(即输入字符串的大小)来最大化大小。如果不可能,则搜索较小尺寸的len。
要检查二进制搜索给出的长度是否有k个唯一字符,可以使用一组插入所有字符,然后如果set的大小小于k,则不可能给出答案,否则二进制搜索给出的答案是最大的答案。
二进制搜索在这里适用,因为已知对于某个len是否可行,并且我们希望将len最大化,因此搜索域会发生变化,然后从len到n进行搜索。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function that returns true if there
// is a substring of length len
// with <=k unique characters
bool isValidLen(string s, int len, int k)
{
// Size of the string
int n = s.size();
// Map to store the characters
// and their frequency
unordered_map mp;
int right = 0;
// Update the map for the
// first substring
while (right < len) {
mp[s[right]]++;
right++;
}
if (mp.size() <= k)
return true;
// Check for the rest of the substrings
while (right < n) {
// Add the new character
mp[s[right]]++;
// Remove the first character
// of the previous window
mp[s[right - len]]--;
// Update the map
if (mp[s[right - len]] == 0)
mp.erase(s[right - len]);
if (mp.size() <= k)
return true;
right++;
}
return mp.size() <= k;
}
// Function to return the length of the
// longest substring which has K
// unique characters
int maxLenSubStr(string s, int k)
{
// Check if the complete string
// contains K unique characters
set uni;
for (auto x : s)
uni.insert(x);
if (uni.size() < k)
return -1;
// Size of the string
int n = s.size();
// Apply binary search
int lo = -1, hi = n + 1;
while (hi - lo > 1) {
int mid = lo + hi >> 1;
if (isValidLen(s, mid, k))
lo = mid;
else
hi = mid;
}
return lo;
}
// Driver code
int main()
{
string s = "aabacbebebe";
int k = 3;
cout << maxLenSubStr(s, k);
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG
{
// Function that returns true if there
// is a subString of length len
// with <=k unique characters
static boolean isValidLen(String s,
int len, int k)
{
// Size of the String
int n = s.length();
// Map to store the characters
// and their frequency
Map mp = new HashMap();
int right = 0;
// Update the map for the
// first subString
while (right < len)
{
if (mp.containsKey(s.charAt(right)))
{
mp.put(s.charAt(right),
mp.get(s.charAt(right)) + 1);
}
else
{
mp.put(s.charAt(right), 1);
}
right++;
}
if (mp.size() <= k)
return true;
// Check for the rest of the subStrings
while (right < n)
{
// Add the new character
if (mp.containsKey(s.charAt(right)))
{
mp.put(s.charAt(right),
mp.get(s.charAt(right)) + 1);
}
else
{
mp.put(s.charAt(right), 1);
}
// Remove the first character
// of the previous window
if (mp.containsKey(s.charAt(right - len)))
{
mp.put(s.charAt(right - len),
mp.get(s.charAt(right - len)) - 1);
}
// Update the map
if (mp.get(s.charAt(right - len)) == 0)
mp.remove(s.charAt(right - len));
if (mp.size() <= k)
return true;
right++;
}
return mp.size() <= k;
}
// Function to return the length of the
// longest subString which has K
// unique characters
static int maxLenSubStr(String s, int k)
{
// Check if the complete String
// contains K unique characters
Set uni = new HashSet();
for (Character x : s.toCharArray())
uni.add(x);
if (uni.size() < k)
return -1;
// Size of the String
int n = s.length();
// Apply binary search
int lo = -1, hi = n + 1;
while (hi - lo > 1)
{
int mid = lo + hi >> 1;
if (isValidLen(s, mid, k))
lo = mid;
else
hi = mid;
}
return lo;
}
// Driver code
public static void main(String[] args)
{
String s = "aabacbebebe";
int k = 3;
System.out.print(maxLenSubStr(s, k));
}
}
// This code is contributed by Rajput-Ji
Python3
# Python3 implementation of the approach
# Function that returns True if there
# is a sub of length len
# with <=k unique characters
def isValidLen(s, lenn, k):
# Size of the
n = len(s)
# Map to store the characters
# and their frequency
mp = dict()
right = 0
# Update the map for the
# first sub
while (right < lenn):
mp[s[right]] = mp.get(s[right], 0) + 1
right += 1
if (len(mp) <= k):
return True
# Check for the rest of the subs
while (right < n):
# Add the new character
mp[s[right]] = mp.get(s[right], 0) + 1
# Remove the first character
# of the previous window
mp[s[right - lenn]] -= 1
# Update the map
if (mp[s[right - lenn]] == 0):
del mp[s[right - lenn]]
if (len(mp) <= k):
return True
right += 1
return len(mp)<= k
# Function to return the length of the
# longest sub which has K
# unique characters
def maxLenSubStr(s, k):
# Check if the complete
# contains K unique characters
uni = dict()
for x in s:
uni[x] = 1
if (len(uni) < k):
return -1
# Size of the
n = len(s)
# Apply binary search
lo = -1
hi = n + 1
while (hi - lo > 1):
mid = lo + hi >> 1
if (isValidLen(s, mid, k)):
lo = mid
else:
hi = mid
return lo
# Driver code
s = "aabacbebebe"
k = 3
print(maxLenSubStr(s, k))
# This code is contributed by Mohit Kumar
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG
{
// Function that returns true if there
// is a subString of length len
// with <=k unique characters
static bool isValidLen(String s,
int len, int k)
{
// Size of the String
int n = s.Length;
// Map to store the characters
// and their frequency
Dictionary mp = new Dictionary();
int right = 0;
// Update the map for the
// first subString
while (right < len)
{
if (mp.ContainsKey(s[right]))
{
mp[s[right]] = mp[s[right]] + 1;
}
else
{
mp.Add(s[right], 1);
}
right++;
}
if (mp.Count <= k)
return true;
// Check for the rest of the subStrings
while (right < n)
{
// Add the new character
if (mp.ContainsKey(s[right]))
{
mp[s[right]] = mp[s[right]] + 1;
}
else
{
mp.Add(s[right], 1);
}
// Remove the first character
// of the previous window
if (mp.ContainsKey(s[right - len]))
{
mp[s[right - len]] = mp[s[right - len]] - 1;
}
// Update the map
if (mp[s[right - len]] == 0)
mp.Remove(s[right - len]);
if (mp.Count <= k)
return true;
right++;
}
return mp.Count <= k;
}
// Function to return the length of the
// longest subString which has K
// unique characters
static int maxLenSubStr(String s, int k)
{
// Check if the complete String
// contains K unique characters
HashSet uni = new HashSet();
foreach (char x in s.ToCharArray())
uni.Add(x);
if (uni.Count < k)
return -1;
// Size of the String
int n = s.Length;
// Apply binary search
int lo = -1, hi = n + 1;
while (hi - lo > 1)
{
int mid = lo + hi >> 1;
if (isValidLen(s, mid, k))
lo = mid;
else
hi = mid;
}
return lo;
}
// Driver code
public static void Main(String[] args)
{
String s = "aabacbebebe";
int k = 3;
Console.Write(maxLenSubStr(s, k));
}
}
// This code is contributed by Rajput-Ji
输出:
7