更多精彩文章请关注微信公众号:TanLiuYi00
今天给大家分享一道 facebook 的面试题,也就是 Leetcode 209. 长度最小的子数组,提供滑动窗口解题思路,供大家参考。
题目
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
滑动窗口解法
假设下标从 i 到 j 连续子数组元素和为 sum,如下图示:
如果当前的 sum 小于 s,则将下标 j 右移,将其后面一个数组元素也加入到 sum 中,如下如示:
依次类推,如果 sum 仍然小于 s,继续往下标 j 后面多加一个数组元素,直到最后 sum > s,就找到了一个满足题意的连续子数组记录长度,如下图示:
然后再从下标 i 不断右移,缩小该连续子数组的和 sum,在将 i 不断右移过程中,某一时刻 sum < s,如下图示:
此时下标 j 又开始不断右移,找到一个连续子数组的和 sum > s,依次类推。
整个过程一直保持着一个窗口,其长度不是固定的,但是是被 i 和 j 这两个索引所定义的,窗口不停向前滑动去寻找满足题意的连续子数组。
Show me the Code
// c 语言版本
int minSubArrayLen(int s, int* nums, int numsSize){
int sum = 0; // 窗口中数组元素的和
int res = numsSize + 1; // 最小的连续子数组的长度
int left = 0, right = -1; // nums[left...right] 为滑动窗口
while (left < numsSize) {
// sum 小于 s,窗口的右边界向前拓展,但要保证右边界 right 不越界
if ((right < numsSize - 1) && (sum < s)) {
sum += nums[++right];
// sum 大于等于 s,窗口的左边界向前行进
} else {
sum -= nums[left++];
}
// 找到可行的连续子数组,取 res 和目前连续子数组的长度(前闭右闭,长度 +1)的最小值
if (sum >= s) {
res = res < right - left + 1 ? res : right - left + 1;
}
}
// 不存在符合条件的子数组,则返回 0,否则返回最小的连续子数组的长度
return res == numsSize + 1 ? 0 : res;
}
运行结果:
更多精彩:
关注微信公众号:TanLiuYi00