Bootstrap

脸书面试题 leetcode 209. 长度最小的子数组(滑动窗口)

更多精彩文章请关注微信公众号: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

图片

;