python无重复最长子串与三数之和

58 阅读2分钟

一、无重复字符的最长子串:滑动窗口的巧妙应用

题目回顾

给定一个字符串 s,找出其中不含有重复字符的最长子串的长度。例如输入 s = "abcabcbb",输出为 3,因为最长无重复子串是 "abc"(或 "bca""cab")。

滑动窗口解法原理

滑动窗口通过双指针维护一个 “动态窗口”,窗口内始终是无重复字符的子串:

  1. 右指针扩展窗口:逐个遍历字符,尝试将当前字符加入窗口;
  2. 左指针收缩窗口:若当前字符已在窗口中,不断右移左指针,直到移除重复字符;
  3. 记录最大长度:每次调整窗口后,计算窗口长度并更新最大值。

代码实现与解析

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]