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;
    }
};
    
相关推荐
董董灿是个攻城狮6 小时前
AI视觉连载8:传统 CV 之边缘检测
算法
blasit12 小时前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
AI软著研究员13 小时前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish13 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱14 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
地平线开发者1 天前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮1 天前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者1 天前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考1 天前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
HXhlx1 天前
CART决策树基本原理
算法·机器学习