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;
    }
};
    
相关推荐
艾莉丝努力练剑34 分钟前
【C语言16天强化训练】从基础入门到进阶:Day 11
c语言·学习·算法
Pafey2 小时前
【Deepseek】Windows MFC/Win32 常用核心 API 汇总
c++·windows·mfc
侯杰2 小时前
C++ 线程安全初始化机制详解与实践
c++
浩少7022 小时前
LeetCode-22day:多维动态规划
算法·leetcode·动态规划
每天敲200行代码3 小时前
QT 概述(背景介绍、搭建开发环境、Qt Creator、程序、项目文件解析、编程注意事项)
c++·qt
岁月静好20253 小时前
Leetcode 深度优先搜索 (15)
算法·leetcode·深度优先
离越词4 小时前
C++day1作业
数据结构·c++·算法
凤年徐4 小时前
【数据结构与算法】LeetCode 20.有效的括号
c语言·数据结构·算法·leetcode
道剑剑非道5 小时前
VxWorks 核心数据结构详解 【消息队列、环形缓冲区、管道、FIFO、双缓冲区、共享内存】
数据结构·c·vxworks
医工交叉实验工坊5 小时前
R 语言 ComplexUpset 包实战:替代 Venn 图的高级集合可视化方案
算法·r语言