主页 > 游戏开发  > 

代码随想录第一章数组209.长度最小的子数组

代码随想录第一章数组209.长度最小的子数组
代码随想录 第一章 数组 209.长度最小的子数组 题目: 209.长度最小的子数组

题目描述:

给定一个含有 n​ 个正整数的数组和一个正整数 target​ 。

找出该数组中满足其总和大于等于target​ 的长度最小的 子数组 [numsₗ, numsₗ₊₁, ..., numsᵣ₋₁, numsᵣ]​ ,并返回其长度 。 如果不存在符合条件的子数组,返回 0​ 。

一、思想

滑动窗口的核心思想是就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。

在本题中实现滑动窗口,主要确定如下三点:

窗口内是什么?如何移动窗口的起始位置?如何移动窗口的结束位置?

窗口就是 满足其和 ≥ target​ 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于等于target​了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

解题的关键在于窗口的起始位置如何移动。

滑动窗口算法详解(示例:nums=[2,3,1,2,4,3]​, target=7​) 右指针当前元素窗口范围累计和是否触发收缩操作记录最小长度左指针位置变化轨迹02​[0,0]​2否右移 →∞0 → 013​[0,1]​5否右移 →∞0 → 021​[0,2]​6否右移 →∞0 → 032​[0,3]​8是① 长度=4 → subLength=4​② sum-=2​ → sum=6​③ 左指针移动 →left=1​40 → 144​[1,4]​10是① 长度=4 → 不更新② sum-=3 ​→ sum=7​③ 左移 → left=2​④ 再次检测 → 长度=3 → subLength=3​⑤ sum-=1​ → sum=6​⑥ 左指针移动→ left=3​31 → 353​[3,5]​9是① 长度=3 → 不更新② sum-=2​ → sum=7​③ 左移 → left=4​④ 再次检测 → 长度=2 → subLength=2​⑤ sum-=4​ → sum=3​⑥ 左指针移动→ left=5​23 → 5 二、代码 /** * 类Solution:解决问题 */ class Solution { public: /** * 函数minSubArrayLen:寻找最短的子数组,其和至少为target * @param target 目标和 * @param nums 整数数组 * @return 返回最短子数组的长度,如果不存在满足条件的子数组,返回0 */ int minSubArrayLen(int target, vector<int> &nums) { // 初始化结果为最大整数 int result = INT_MAX; // 初始化当前和为0 int sum = 0; // 初始化子数组的起始位置为0 int i = 0; // 初始化子数组的长度为0 int subLength = 0; // 遍历数组 for (int j = 0; j < nums.size(); j++) { // 更新当前和 sum += nums[j]; // 当当前和大于等于目标和时 while (sum >= target) { // 更新子数组的长度 subLength = j - i + 1; // 更新结果为当前结果和子数组长度的最小值 result = result < subLength ? result : subLength; // 更新当前和 sum -= nums[i++]; } } // 如果结果仍为最大整数,返回0,否则返回结果 return result == INT_MAX ? 0 : result; } }; 三、解析 1. 算法工作原理分解 1.1 初始化阶段

核心变量定义

int result = INT_MAX; // 最小长度记录器(初始设为极大值) int sum = 0; // 窗口和累计器 int i = 0; // 左指针(窗口起始位置)

初始状态

窗口范围:[0, 0)​(空窗口)示例:nums=[2,3,1,2,4,3]​ 初始时 sum=0​ 1.2 右指针主导窗口扩展

遍历机制

for(int j=0; j<nums.size(); j++) { // j为右指针 sum += nums[j]; // 动态扩展窗口右边界

操作特点

右指针 j​ 单向前进(从0到n-1)每次扩展必然添加新元素到窗口示例:当 j=3​ 时,窗口扩展为 [2,3,1,2]​ 1.3 收缩条件检测

触发条件

while(sum >= target) { // 必须用while循环

检测逻辑

当窗口和 sum​ ≥ target​ 时进入收缩阶段示例:j=3​ 时 sum=8 ≥7​ 触发收缩 1.4 窗口收缩与最小长度更新

收缩操作流程

计算当前窗口长度

subLength = j - i + 1; // 闭区间长度计算

更新最小长度

result = min(result, subLength); // 取历史最小值

左指针右移

sum -= nums[i++]; // 先减元素值,再移动左指针

操作示例

当窗口为 [2,3,1,2]​ 时:

计算长度 4​ → 更新 result=4​收缩后窗口变为 [3,1,2]​,sum=6​ 1.5 连续收缩机制

多轮收缩场景

while(sum >= target) { // 可能执行多次收缩 // 上述收缩操作 }

必要性

确保找到以当前右指针为终点的最小窗口

示例:当 j=4​ 时窗口 [1,4]​ 需连续收缩两次

第一轮收缩:窗口 [2,4]​,sum=7​第二轮收缩:窗口 [3,4]​,sum=6​(退出循环) 1.6 最终结果处理

无效结果判断

return (result == INT_MAX) ? 0 : result;

逻辑意义

若从未找到有效窗口(result​未更新),返回0示例最终结果:result=2​(窗口 [4,3]​) 2. 关键点说明 操作阶段时间复杂度保障机制示例中的操作表现右指针扩展单层for​循环 → O(n)右指针完整遍历数组(6次移动)左指针收缩每个元素最多被左指针访问一次 → O(n)左指针共移动4次(0→1→2→3→5)窗口计算即时更新result​ → O(1) 操作3次有效更新(4→3→2)循环检测​while​确保完全收缩 → 无遗漏步骤5中触发两次连续收缩 四、复杂度分析 时间复杂度:O(n) 滑动窗口的 左指针 ​left​​ 和右指针 ​right​​ 均单向移动,每个元素最多被访问两次(右指针扩展时访问一次,左指针收缩时访问一次)。对于长度为 n​ 的数组,总操作次数为 2n​ 次,最终时间复杂度为线性级别。空间复杂度:O(1) 仅使用固定数量的额外空间(sum​、left​、result​ 等整型变量),空间消耗与输入规模 n​ 无关。

标签:

代码随想录第一章数组209.长度最小的子数组由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“代码随想录第一章数组209.长度最小的子数组