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;
    }
};
    
相关推荐
是店小二呀11 分钟前
【动态规划 | 子序列问题】子序列问题的最优解:动态规划方法详解
算法·动态规划·代理模式
啊我不会诶1 小时前
BD202402跑步 线性求逆元 素数筛 数学
学习·算法·补题
遇见尚硅谷1 小时前
挑战指针题
c语言·数据结构·算法
是阿建吖!1 小时前
【优选算法】分治--归并排序
数据结构·算法·排序算法
AWEN_331 小时前
最大重复子字符串
leetcode
CoovallyAIHub1 小时前
轻量?智能?协同?你选的标注工具,到底有没有帮你提效?
深度学习·算法·计算机视觉
roman_日积跬步-终至千里2 小时前
【机器学习】(算法优化一)集成学习之:装袋算法(Bagging):装袋决策树、随机森林、极端随机树
算法·机器学习·集成学习
打点计时器2 小时前
Onnx模型部署到Arm64进行推理
c++
孟柯coding2 小时前
链表问题解决分析框架
数据结构·链表