一、无重复字符的最长子串:滑动窗口的巧妙应用
题目回顾
给定一个字符串 s,找出其中不含有重复字符的最长子串的长度。例如输入 s = "abcabcbb",输出为 3,因为最长无重复子串是 "abc"(或 "bca"、"cab")。
滑动窗口解法原理
滑动窗口通过双指针维护一个 “动态窗口”,窗口内始终是无重复字符的子串:
- 右指针扩展窗口:逐个遍历字符,尝试将当前字符加入窗口;
- 左指针收缩窗口:若当前字符已在窗口中,不断右移左指针,直到移除重复字符;
- 记录最大长度:每次调整窗口后,计算窗口长度并更新最大值。
代码实现与解析
def longest_subString(s):
char_set = set() # 存储窗口内的字符,保证唯一性
left = 0 # 窗口左边界指针
max_len = 0 # 记录最长子串长度
for right in range(len(s)): # 右指针遍历字符串
# 若当前字符重复,收缩左边界
while s[right] in char_set:
char_set.remove(s[left])
left += 1
# 添加当前字符到窗口
char_set.add(s[right])
# 更新最大长度(窗口长度 = right - left + 1)
max_len = max(max_len, right - left + 1)
return max_len
# 测试
s = "abcabcbb"
print(longest_subString(s)) # 输出:3
二、三数之和:从暴力枚举到双指针优化
题目回顾
给定整数数组 nums,找出所有和为 0 且不重复的三元组 [nums[i], nums[j], nums[k]](i≠j≠k)。例如输入 nums = [-1,0,1,2,-1,-4],输出为 [[-1,-1,2],[-1,0,1]]。
暴力解法的问题
暴力解法通过三层循环枚举所有三元组,再用集合去重,代码如下:
def three_num_brute(nums):
res = set()
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
for k in range(j + 1, n):
if nums[i] + nums[j] + nums[k] == 0:
# 排序后转元组,利用集合去重
tmp = tuple(sorted([nums[i], nums[j], nums[k]]))
res.add(tmp)
return [list(item) for item in res]