LeetCode:209.长度最小的子数组&&3.无重复字符的最长子串

做滑动窗口之前必须先思考几个问题:

1. 窗口的 "边界" 是什么?
2. 窗口的 "扩大" 和 "收缩" 条件是什么?
  • 何时扩大窗口 :一般由 right 指针负责,当窗口内元素不满足条件时(如和小于目标值、未包含所有所需字符),right 右移纳入新元素。
  • 何时收缩窗口 :一般由 left 指针负责,当窗口内元素满足条件时(如和大于等于目标值、包含多余字符),left 右移减少元素,试图找到更优解。
  • 收缩时用 if 还是 while
    • 若只需找到一个可行解后停止收缩(如判断是否存在),用 if
    • 若需在满足条件时持续收缩以寻找最优解(如最短长度),必须用 while
3. 窗口需要 "维护" 什么信息?

滑动窗口的核心是 "用左右指针维护一个动态区间,通过明确的扩大 / 收缩规则,在一次遍历中找到最优解"。窗口的 "动态平衡"(扩大与收缩的条件)是解题关键。

之前滑动窗口讲述过,当问题涉及连续的子数组、子串或区间,且需要对区间内的元素进行整体处理(如求和、计数、判断是否满足条件)时,我们可以优先使用滑动窗口。

本题的边界就是要求子数组内元素总和大于等于目标值,维护的就是最小满足条件的子数组长度。当子数组总和不满足target,右指针移动,纳入新元素;当子数组总和满足target,左指针移动,并且用while做持续收缩来优化结果。

C++代码:

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int minlen = INT_MAX;
        int tar = 0;      // 窗口内元素的和
        int left = 0;     // 左指针(下标)
        
        // 右指针遍历数组,扩大窗口
        for (int right = 0; right < n; right++) {
            tar += nums[right];  // 将当前元素纳入窗口
            
            // 当窗口和 >= target 时,尝试收缩左指针,寻找最小长度
            while (tar >= target) {
                int current_len = right - left + 1;  // 当前窗口长度
                minlen = min(minlen, current_len);   // 更新最小长度
                
                // 收缩左指针(从窗口中移除左元素)
                tar -= nums[left];
                left++;
            }
        }
        
        // 若未找到符合条件的子数组,返回0
        return minlen == INT_MAX ? 0 : minlen;
    }
};

本题也是一个滑动窗口的问题,维护的就是一个无重复字符的子字符串区间当窗口内无重复字符时right 右移以纳入新字符,扩大窗口范围。当窗口内出现重复字符时left 右移以移除左侧字符,收缩窗口范围,直至窗口内无重复字符。当 s[right] 与窗口内字符重复时,可能需要连续收缩多次才能移除所有重复影响,所以收缩时应该用while连续收缩。

C++代码:

cpp 复制代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int left = 0;
        int maxlen = 0;
        int n = s.size();
        unordered_set<char> uset;
        
        for (int right = 0; right < n; right++) {
            // 若当前字符已在集合中(重复),收缩左窗口并移除离开的元素
            while (uset.find(s[right]) != uset.end()) {
                uset.erase(s[left]);  // 关键:移除左指针指向的元素
                left++;
            }
            // 将当前字符加入集合,更新最大长度
            uset.insert(s[right]);
            maxlen = max(maxlen, right - left + 1);  // 计算当前窗口长度 [left, right]
        }
        
        return maxlen;
    }
};
    
相关推荐
BothSavage6 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn6 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
烬羽7 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
郝学胜_神的一滴8 小时前
CMake 034:生成器表达式:解耦构建时序、精简分支逻辑的终极利器
c++·cmake
先吃饱再说1 天前
判断回文字符串,从一行代码到双指针优化
算法
见过夏天1 天前
C++ 基础入门完全指南
c++
黄敬峰1 天前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术1 天前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六1 天前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程