【算法题】滑动窗口(一)

滑动窗口是处理子串/子数组问题的经典双指针技巧,核心是通过维护一个"窗口"(左右指针界定的区间),动态调整窗口范围来满足题目条件,从而高效求解问题。

一、无重复字符的最长子串

题目描述:

给定一个字符串 s,找出其中不含有重复字符的最长子串的长度。

示例

  • 输入:s = "abcabcbb",输出:3(最长子串为 "abc"
  • 输入:s = "bbbbb",输出:1(最长子串为 "b"

解题思路:

用滑动窗口维护"无重复字符的子串",配合哈希数组记录字符出现次数:

  1. 定义窗口左右指针 leftright,哈希数组 hash[128] 统计窗口内字符出现次数。
  2. 右指针 right 遍历字符串,将当前字符加入窗口并更新出现次数。
  3. 若当前字符出现次数超过1(窗口内有重复),移动左指针缩小窗口,直到无重复。
  4. 每次调整后,更新最长子串长度。

完整代码:

cpp 复制代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int hash[128] = {0};
        int ret = 0;
        for(int left = 0, right = 0; right < s.size(); right++) {
            hash[s[right]]++;
            while(hash[s[right]] > 1) {
                hash[s[left++]]--;
            }
            ret = max(ret, right - left + 1);
        }
        return ret;
    }
};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),每个字符最多被左右指针各遍历一次。
  • 空间复杂度:O(1)O(1)O(1),哈希数组大小固定(128个ASCII字符)。

二、长度最小的子数组

题目描述:

给定含 n 个正整数的数组和正整数 target,找出总和≥target的长度最小的子数组,返回其长度;若不存在则返回 0

示例

  • 输入:target = 7, nums = [2,3,1,2,4,3],输出:2(子数组 [4,3]

解题思路:

用滑动窗口维护"总和≥target的子数组",动态缩小窗口找最小长度:

  1. 定义窗口左右指针 leftright,变量 sum 记录窗口内元素和。
  2. 右指针 right 遍历数组,累加元素和到 sum
  3. sum ≥ target,尝试移动左指针缩小窗口(同时更新最小长度),直到 sum < target
  4. 遍历结束后,若未找到符合条件的子数组则返回 0

完整代码:

cpp 复制代码
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum = 0, len = INT_MAX;
        for(int left = 0, right = 0; right < nums.size(); right++) {
            sum += nums[right];
            while(sum >= target) {
                len = min(len, right - left + 1);
                sum -= nums[left++];
            }
        }
        return len == INT_MAX ? 0 : len;
    }
};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),每个元素最多被左右指针各遍历一次。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

三、最大连续1的个数 III

题目描述:

给定二进制数组 nums 和整数 k,最多可以翻转 k0,返回操作后数组中连续 1 的最大个数。

示例

  • 输入:nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2,输出:6(翻转后最长子数组为 [1,1,1,0,0,1,1,1,1,1]

解题思路:

用滑动窗口维护"最多包含 k0 的子数组"(即允许翻转 k0 后的连续1区间):

  1. 定义窗口左右指针 leftright,变量 zeros 统计窗口内 0 的个数。
  2. 右指针 right 遍历数组,遇到 0zeros++
  3. zeros > k,移动左指针缩小窗口,直到 zeros ≤ k
  4. 每次调整后,更新最长子数组长度。

完整代码:

cpp 复制代码
class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int ret = 0;
        for(int left = 0, right = 0, zeros = 0; right < nums.size(); right++) {
            if(nums[right] == 0) zeros++;
            while(zeros > k) {
                if(nums[left++] == 0) zeros--;
            }
            ret = max(ret, right - left + 1);
        }
        return ret;
    }
};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),每个元素最多被左右指针各遍历一次。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。

四、将x减到0的最小操作数

题目描述:

给定整数数组 nums 和整数 x,每次操作移除数组最左或最右元素并从 x 中减去该元素值,要求将 x 恰好减到 0,返回最小操作数;否则返回 -1

示例

  • 输入:nums = [1,1,4,2,3], x = 5,输出:2(移除后两个元素 2+3=5

解题思路:
转化问题 :"最小操作数"等价于"数组中最长的、和为 sum(nums)-x 的子数组"(因为移除的元素是数组两端,剩余的中间子数组和为 sum-x)。

  1. 计算数组总和 sum,目标子数组和为 target = sum - x(若 target < 0,直接返回 -1)。
  2. 用滑动窗口找最长的、和为 target 的子数组。
  3. 若找到该子数组,最小操作数为 数组长度 - 子数组长度;否则返回 -1

完整代码:

cpp 复制代码
class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int sum = 0;
        for(auto n : nums) sum += n;
        int target = sum - x;
        if(target < 0) return -1;
        
        int ret = -1;
        for(int left = 0, right = 0, tmp = 0; right < nums.size(); right++) {
            tmp += nums[right];
            while(tmp > target) tmp -= nums[left++];
            if(tmp == target)
                ret = max(ret, right - left + 1);
        }
        return ret == -1 ? -1 : nums.size() - ret;
    }
};

复杂度分析:

  • 时间复杂度:O(n)O(n)O(n),每个元素最多被左右指针各遍历一次。
  • 空间复杂度:O(1)O(1)O(1),仅用常数级额外变量。
相关推荐
程序员贺加贝13 小时前
报表大 IN 优化:一条 product_profile 超大 IN SQL 背后的报表任务治理
算法·性能优化
知无不研14 小时前
std::function在使用时遇到的问题
c++·算法·st·function
薛定e的猫咪14 小时前
(IEEE Transactions 2025)自适应元强化学习动态柔性作业车间调度框架
网络·人工智能·算法
码场老菜鸟14 小时前
C++ 指针的深度理解与应用
java·c++·算法
fpcc15 小时前
数据结构和算法—最短路径的算法
数据结构·算法
茉莉玫瑰花茶15 小时前
RAG 数据检索
人工智能·算法·机器学习
speop15 小时前
hell-gpu| TASK01-2
linux·运维·算法
Navigator_Z16 小时前
LeetCode //C - 1223. Dice Roll Simulation
c语言·算法·leetcode
171320330计算机毕设编程16 小时前
2027计算机毕设五大方向对比&选题推荐
java·ide·python·算法·django·php·推荐算法
万物智能16 小时前
设备树DTS-【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
后端·算法