
是关于 "无重复字符的最长子串"问题 的滑动窗口解法。以下从题目分析、算法分析和代码编写三个方面进行总结:
题目分析
-
问题 :给定一个字符串
s,找出其中不含有重复字符 的最长连续子串的长度。 -
输入 :一个字符串
s。 -
输出:一个整数,表示最长无重复字符子串的长度。
-
示例 :对于字符串
"abcabcbb",最长无重复字符子串是"abc",长度为 3。
算法分析
您笔记中清晰地对比了两种思路:
-
暴力枚举 + 哈希表判断重复:
-
思路:枚举所有可能的子串(通过双重循环),对于每个子串,使用哈希表判断其中是否有重复字符。
-
缺点:时间复杂度为 O(n²) 或 O(n³),效率低。
-
-
滑动窗口(双指针)法(最优解):
-
核心思想 :利用两个同向移动的指针
left和right构成一个窗口,表示当前考察的子串。通过动态调整窗口边界,确保窗口内始终无重复字符,同时记录最大窗口长度。 -
步骤:
-
初始化 :
left = 0,right = 0, 一个哈希集合set用于存储窗口内的字符,maxLen = 0。 -
进窗口 :将
s[right]加入集合set,然后right右移。 -
判断与去重 :如果加入后
set中s[right-1]已存在(即出现重复),则不断从set中移除s[left]并将left右移,直到重复被消除。 -
更新结果 :此时窗口内无重复,计算当前窗口长度
right - left,并更新maxLen。 -
重复步骤 2-4,直到
right到达字符串末尾。
-
-
优化:可以使用数组(ASCII 码共128个字符)代替哈希集合,以提升速度。
-
优点:每个字符最多被访问两次(进窗口和出窗口各一次),时间复杂度 O(n),空间复杂度 O(字符集大小)。
-
代码编写
以下是修正和完善您笔记中代码后的 Java 实现,提供两种版本:
版本一:使用 HashSet(易于理解)
import java.util.HashSet;
import java.util.Set;
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set = new HashSet<>();
int left = 0, right = 0;
int maxLen = 0;
while (right < s.length()) {
char c = s.charAt(right);
// 如果字符已存在,则移动左指针直到重复字符被移除
while (set.contains(c)) {
set.remove(s.charAt(left));
left++;
}
// 将当前字符加入集合
set.add(c);
// 更新最大长度
maxLen = Math.max(maxLen, right - left + 1);
right++;
}
return maxLen;
}
}
版本二:使用数组(更高效)
class Solution {
public int lengthOfLongestSubstring(String s) {
int[] hash = new int[128]; // ASCII 字符集
int left = 0, right = 0;
int maxLen = 0;
while (right < s.length()) {
char c = s.charAt(right);
hash[c]++; // 进窗口
// 判断:如果当前字符计数>1,说明有重复,移动左指针去重
while (hash[c] > 1) {
char leftChar = s.charAt(left);
hash[leftChar]--; // 出窗口
left++;
}
// 更新结果
maxLen = Math.max(maxLen, right - left + 1);
right++;
}
return maxLen;
}
}
public int longestOnes(int[] nums, int k) {
int left=0;
int count=0;
int ret=0;
for(int right=0;right<nums.length;right++){
if(nums[right]==0){
count++;
}
while(count>k){
if(nums[left++]==0){
count--;
}
}
ret=Math.max(ret,right-left+1);
}
return ret;
}
代码说明:
-
进窗口:将右指针指向的字符加入集合或数组计数。
-
判断与去重:如果加入后导致重复(集合已存在或数组计数>1),则持续移动左指针,从集合/数组中移除字符,直到重复消除。
-
更新结果:每次窗口内无重复时,计算当前窗口长度并更新最大值。
-
移动右指针:继续扩大窗口。
此解法是解决"无重复字符的最长子串"问题的标准滑动窗口方法,高效且易于理解。