首页 > 技术文章 > 长度最小的子数组之O(n)解法

syhyfh 2020-04-16 11:15 原文

题目:对角线遍历

问题描述:

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。

解决思路:

由于题目中给出的数组中的元素全都是正整数并且需要不断计算该数组中子数组的和,所以我们可以利用双指针的滑动窗口法来解决这个问题。

定义两个指针left和right分别为滑动窗口的左端点和右端点,由于刚开始left和right之间没有元素,所以定义right的初始值为-1,left的初始值为0。并且这两个指针均向右移动。在移动过程中,如果子数组的和 < s,那么我们就需要将right向右移动并且加上当前索引的元素值以扩大移动窗口的范围,反之则需要减去当前索引的元素值并且将left向左移动以缩小移动窗口的范围。

我们还需要定义一个最终的返回值minVal。需要注意的是:我们需要将该值的初始值设定为比数组的长度大一些的值。不能等于的原因是:若程序返回结果为数组长度,那么就会造成minVal与minVal的初始值相等,这时就会发生本该返回数组长度却返回0的错误情况。不能小于的原因是:若程序返回结果为数组长度,那么就会造成minVal最终的值为一个小于数组长度的值,这时就会发生本该返回数组长度却返回小于数组长度的minVal的错误情况。

解决代码:


class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int left = 0;
        int right = -1;			
        int sum = 0;
        int len = nums.length;
        int minVal = len + 10000;	
        while(left < len) {
            if(right + 1 < len && sum < s) {		
                right++;
                sum += nums[right];
            } else {								
                sum -= nums[left];
                left++;
            }
            
            if(sum >= s) {
            	minVal = Math.min(minVal, right - left + 1);
            }
        }
        
        return minVal == len+10000 ? 0 : minVal;
    }
}

推荐阅读