力扣209. 长度最小的子数组
题目来源(力扣):
https://leetcode.cn/problems/minimum-size-subarray-sum/description/
题目描述:
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的 子数组[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
基本思路:
最基本的算法之一,考察对"滑动窗口"知识的掌握和基础编码能力。
滑动窗口法还会在后面的很多算法题目中遇到~
难点主要是边界left,right更新处理,
《代码随想录中》常用的写法是每一步更新左区间都尝试更新答案,
和《代码随想录》中滑动窗口写法不同,我这里采用的方式是每次更新右区间,满足条件后,继续更新左区间,直到找到当前以右区间为边界的最小的子数组,然后进行一次更新即可;理论上会少很多更新次数,从而优化速率,如下:
代码实现:
class Solution
{
public:
int minSubArrayLen(int target, vector<int> &nums)
{
int ans = nums.size() + 1, l = 0, r = 0;
int tmp = 0;
while (l <= r && r < nums.size())
{
tmp += nums[r];
if (tmp >= target)//满足条件
{
while (l < r && tmp - nums[l] >= target)//不是每一步都更新ans,而是直接缩短l的位置
{
tmp -= nums[l];
l++;
}
if (ans > r - l + 1)//然后进行一次更新
ans = r - l + 1;
//tmp -= nums[l];//
//l++;//这2句可以不写(想想为什么)
}
r++;
}
if (ans == nums.size() + 1)
return 0;
return ans;
}
};
时间复杂度
O(n),n为数组长度
看似2个while嵌套着,实际上left、right各自都只会从0到n移动,
只不过每次先right移动,当right到合适的位置(这里是移动到某个位置使得子数组的累计和大于了target)时暂停移动,让left移动
然后当left移动到合适的位置(这里是移动到某个位置使得子数组的累计和又小于了target)时暂停移动,让right移动
因此很类似于《操作系统》中进程并发执行的过程~
(怎么样,计算机和神奇吧,各个知识点都是有内在关联的~)
more
如果你还不了解进程并发执行,那建议补充一下《操作系统》的知识
毕竟计算机是一个庞大的体系,算法和数据结构只是其中的一部分,更像是外功
而操作系统、计算机网络等理论知识,是计算机世界的基础成分,类似于内功
内外兼修才能真正成为武林高手
浙公网安备 33010602011771号