Problem Statement
Given a string, find the length of the longest possible substring in it that has exactly K distinct characters. If there is no possible substring then print -1.
You can assume that K is less than or equal to the length of the given string.
Example 1:
Input: S = "aabacbebebe", K = 3
Output: 7
Explanation: "cbebebe" is the longest substring with 3 distinct characters.Example 2:
Input:
S = "aaaa", K = 2
Output: -1
Explanation: There's no substring with 2 distinct characters.Solution
This problem is based on the variable-size sliding window pattern. We have already solved a similar problem Smallest Subarray with a given Sum using this pattern. We will use the same strategy to solve this problem as well.
- Consider each substring as a sliding window.
- Start with a sliding window of size
1(windowStart=0, windowEnd=0). - Initialize a HashMap that stores the character count for each character in the current window.
- Iterate over the string and insert new characters in the HashMap until we have exactly
Kdistinct characters in the HashMap.- At this point, we have a window (subarray) that conforms to our criteria of having exactly
Kunique characters. So remember the length of this window as the longest window so far. - However, if the count of distinct characters in the HashMap is greater than
K, then we will start shrinking the window from the left until the count becomes smaller than or equal toK. To shrink the window, we will need to discard the leftmost element of the window from the HashMap.
- At this point, we have a window (subarray) that conforms to our criteria of having exactly
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
class LongestSubstringWithKUniqueCharacters {
private static int findLengthOfLongestSubstringWithKUniqueCharacters(String s, int k) {
int n = s.length();
int maxLen = -1; // Stores the length of the longest substring with k unique characters found so far.
Map<Character, Integer> windowCharCount = new HashMap<>(); // Stores the character count for each character in the current window
int windowStart = 0;
for(int windowEnd = 0; windowEnd < n; windowEnd++) {
// Add the next character to the sliding window
char c = s.charAt(windowEnd);
windowCharCount.put(c, windowCharCount.getOrDefault(c, 0) + 1);
// Shrink the sliding window, until we have exactly 'k' distinct characters in the window
while(windowCharCount.size() > k) {
char leftChar = s.charAt(windowStart);
// Discard the character at windowStart since we're gonna move it out of the window now.
windowCharCount.put(leftChar, windowCharCount.get(leftChar) - 1);
if(windowCharCount.get(leftChar) == 0) {
windowCharCount.remove(leftChar);
}
windowStart++; // Shrink the window
}
if(windowCharCount.size() == k) {
// Update maximum length found so far
maxLen = Math.max(maxLen, windowEnd-windowStart+1);
}
}
return maxLen;
}
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
String s = keyboard.next();
int k = keyboard.nextInt();
keyboard.close();
System.out.printf("Longest substring with %d unique characters = %d%n", k, findLengthOfLongestSubstringWithKUniqueCharacters(s, k));
}
}