209. 长度最小的子数组(209. Minimum length subarray)

滑动窗口法

class Solution {
    public int minSubArrayLen(int target, int[] nums) {

        /**
         * 滑动窗口
         * 两个指针同向移动,如果当前窗口内的元素和大于target就记录长度,然后left指针右移缩小查找范围
         * 如果小于target,right指针右移扩大查找范围
         */
        int left = 0;
        int right = 0;
        int min = nums.length;
        boolean flag = true;
        int sum = nums[0];

        while (left <= right){

            if (sum >= target){

                /**
                 * flag标志位用来判断min到底有没有修改过,如果没有的话应该返回0
                 */
                min = Math.min(min, right - left + 1);
                left++;
                sum -= nums[left - 1];
                flag = false;
            }

            /**
             * 如果right已经到达右边界但是和还是小于target,说明已经没有满足的区间了,可以直接结束循环了
             */
            else if (sum < target && right == nums.length - 1){
                break;
            }
            else {

                /**
                 * 如果right已经到达右边界,就不应该再增加了
                 */
                if (right + 1 < nums.length) {

                    right++;
                    sum += nums[right];
                }
            }
        }

        return flag == false ? min : 0;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(1)
 */

优化1——简化循环的判定、不使用标志位

class Solution {
    public int minSubArrayLen(int target, int[] nums) {

        /**
         * 滑动窗口
         * 两个指针同向移动,如果当前窗口内的元素和大于target就记录长度,然后left指针右移缩小查找范围
         * 如果小于target,right指针右移扩大查找范围
         */
        int left = 0;
        int right = 0;
        int min = nums.length + 1;
        int sum = nums[0];

        /**
         * 如果left > right,说明有一个元素大于target,那就不需要再循环了,因为最小长度就是1
         */
        while (left <= right){

            if (sum >= target){

                min = Math.min(min, right - left + 1);
                sum -= nums[left++];
            }
            else {

                /**
                 * 如果right已经到达右边界,就不应该再增加了
                 */
                if (right + 1 < nums.length) {
                    sum += nums[++right];
                }
                else {

                    /**
                     * 如果right已经到达右边界但和还是小于target,说明已经没有满足的区间了,可以直接结束循环了
                     */
                    break;
                }
            }
        }

        /**
         * 如果min没有变过,应该返回0
         */
        return min == nums.length + 1 ? 0 : min;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(1)
 */

https://leetcode-cn.com/problems/minimum-size-subarray-sum/

————————

Sliding window method

class Solution {
    public int minSubArrayLen(int target, int[] nums) {

        /**
         * 滑动窗口
         * 两个指针同向移动,如果当前窗口内的元素和大于target就记录长度,然后left指针右移缩小查找范围
         * 如果小于target,right指针右移扩大查找范围
         */
        int left = 0;
        int right = 0;
        int min = nums.length;
        boolean flag = true;
        int sum = nums[0];

        while (left <= right){

            if (sum >= target){

                /**
                 * flag标志位用来判断min到底有没有修改过,如果没有的话应该返回0
                 */
                min = Math.min(min, right - left + 1);
                left++;
                sum -= nums[left - 1];
                flag = false;
            }

            /**
             * 如果right已经到达右边界但是和还是小于target,说明已经没有满足的区间了,可以直接结束循环了
             */
            else if (sum < target && right == nums.length - 1){
                break;
            }
            else {

                /**
                 * 如果right已经到达右边界,就不应该再增加了
                 */
                if (right + 1 < nums.length) {

                    right++;
                    sum += nums[right];
                }
            }
        }

        return flag == false ? min : 0;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(1)
 */

Optimization 1 – simplify the determination of the cycle and do not use the flag bit

class Solution {
    public int minSubArrayLen(int target, int[] nums) {

        /**
         * 滑动窗口
         * 两个指针同向移动,如果当前窗口内的元素和大于target就记录长度,然后left指针右移缩小查找范围
         * 如果小于target,right指针右移扩大查找范围
         */
        int left = 0;
        int right = 0;
        int min = nums.length + 1;
        int sum = nums[0];

        /**
         * 如果left > right,说明有一个元素大于target,那就不需要再循环了,因为最小长度就是1
         */
        while (left <= right){

            if (sum >= target){

                min = Math.min(min, right - left + 1);
                sum -= nums[left++];
            }
            else {

                /**
                 * 如果right已经到达右边界,就不应该再增加了
                 */
                if (right + 1 < nums.length) {
                    sum += nums[++right];
                }
                else {

                    /**
                     * 如果right已经到达右边界但和还是小于target,说明已经没有满足的区间了,可以直接结束循环了
                     */
                    break;
                }
            }
        }

        /**
         * 如果min没有变过,应该返回0
         */
        return min == nums.length + 1 ? 0 : min;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(1)
 */

https://leetcode-cn.com/problems/minimum-size-subarray-sum/