09. 长度最小的子数组
给定一个包含 n 个正整数的数组和一个正整数 target,找出该数组中满足其和 ≥ target 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
暴力解法分析
最直观的思路是枚举所有可能的子数组起点和终点,计算区间和并与 target 比较。虽然逻辑简单,但时间复杂度高达 O(n^2),在数据量较大时极易超时,实际工程中并不推荐。
滑动窗口优化
既然需要寻找连续区间,滑动窗口(双指针)是更优的选择。核心思想是用两个指针 left 和 right 维护一个动态窗口,通过移动指针来调整窗口内的元素和。
具体步骤如下:
- 右指针 right 不断向右扩展,将元素加入窗口,同时累加 sum。
- 当 sum >= target 时,说明当前窗口满足条件。此时尝试收缩左边界 left,更新最小长度 len,并从 sum 中减去 nums[left]。
- 重复上述过程,直到 right 遍历完整个数组。
为什么这样做效率高?因为 left 和 right 都只向右移动,每个元素最多被访问两次(一次进窗口,一次出窗口),总时间复杂度降为 O(n)。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size(), sum = 0, len = INT_MAX;
for (int left = 0, right = 0; right < n; right++) {
sum += nums[right]; // 右指针进窗口
while (sum >= target) { // 满足条件,尝试收缩
len = min(len, right - left + 1);
sum -= nums[left++]; // 左指针出窗口
}
}
return len == INT_MAX ? 0 : len;
}
};
10. 无重复字符的最长子串
给定一个字符串 s,请你找出其中不含有重复字符的 最长子串 的长度。
暴力解法思路
同样可以枚举所有子串起点,利用哈希表统计字符频次来判断是否重复。虽然能通过部分测试用例,但效率依然不如滑动窗口稳定。
滑动窗口 + 哈希表
这道题的关键在于如何快速判断窗口内是否有重复字符。我们可以使用一个大小为 128 的数组(假设 ASCII 码)作为哈希表,记录字符出现的次数。
流程如下:
- 右指针 right 遍历字符串,将字符 ch 计入哈希表。
- 如果 hash[ch] > 1,说明出现重复。此时必须移动左指针 left,直到 hash[ch] 变回 1,即移除掉导致重复的那个旧字符。


