每个字符最多出现两次的最长子字符串
难度:
标签:
题目描述
Given a string
s
, return the maximum length of a substring such that it contains at most two occurrences of each character.
Example 1:
Input: s = "bcbbbcba"
Output: 4
Explanation:
The following substring has a length of 4 and contains at most two occurrences of each character:"bcbbbcba"
.Example 2:
Input: s = "aaaa"
Output: 2
Explanation:
The following substring has a length of 2 and contains at most two occurrences of each character:"aaaa"
.
Constraints:
2 <= s.length <= 100
s
consists only of lowercase English letters.
代码结果
运行时间: 35 ms, 内存: 16.0 MB
/*
* 思路:使用Java Stream的方式,虽然Stream更偏向于函数式编程,处理状态相关的滑动窗口问题比较复杂,
* 所以这里依然用迭代方式来处理窗口滑动,只是尽量利用Stream API来处理其他部分。
*/
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;
public class LongestSubstringWithMaxTwoOccurrencesStream {
public static int findLongestSubstring(String s) {
Map<Character, Integer> charCount = new HashMap<>();
final int[] maxLength = {0};
final int[] start = {0};
IntStream.range(0, s.length()).forEach(end -> {
char endChar = s.charAt(end);
charCount.put(endChar, charCount.getOrDefault(endChar, 0) + 1);
while (charCount.get(endChar) > 2) {
char startChar = s.charAt(start[0]);
charCount.put(startChar, charCount.get(startChar) - 1);
start[0]++;
}
maxLength[0] = Math.max(maxLength[0], end - start[0] + 1);
});
return maxLength[0];
}
public static void main(String[] args) {
System.out.println(findLongestSubstring("bcbbbcba")); // 输出: 4
System.out.println(findLongestSubstring("aaaa")); // 输出: 2
}
}
解释
方法:
该题解采用了滑动窗口的方法。首先定义一个哈希表来记录窗口内各字符的出现次数,以及一个变量来记录最大子字符串的长度。通过一个右指针遍历字符串,并在哈希表中更新该字符的出现次数。如果字符的出现次数超过2,即不满足题目要求,此时通过移动左指针减少该字符的计数,直到该字符的出现次数不超过2。在每次右指针移动后,更新最大长度。这样,当右指针遍历完整个字符串后,可以得到满足条件的最长子字符串的长度。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
在滑动窗口方法中,如何有效地处理字符的计数以确保每次循环的效率?
▷🦆
哈希表在此问题中充当什么角色,为什么选择哈希表作为数据结构来存储字符计数?
▷🦆
当字符的出现次数超过2次,为什么只需要移动左指针来减少字符的计数,而不考虑其他可能的字符?
▷