209.Minimum Size Subarray Sum

209.Minimum Size Subarray Sum

方法1:用双指针滑动窗口。这是一种双指针应用类型题。复杂度O(n)。

class Solution { public:
        int minSubArrayLen(int s, vector<int>& nums) {
                int len=nums.size();
                if(len==0) return 0;
                int left=0,right=0;
                int MinLength;
                int sum=0;
                for(int i=0;i<len;i++){
                        sum+=nums[i];
                        if(sum>=s) break;
                }
                if(sum>=s) MinLength=len;
                else return 0;
                sum=0;
                int new_length=0;
                while(left<len){
                        while(right<len && sum<s){
                                sum+=nums[right];
                                right++;
                        }
                        new_length=right-left;
                        if(sum>=s && MinLength>new_length){
                                MinLength=new_length;
                        }
                        sum-=nums[left];
                        left++;
                }
                return MinLength;
        }

};

方法2:二分法。时间复杂度O(N*logN)

思路:

网上说的一个思路:建立一个比原数组长一位的sums数组,其中sums[i]表示nums数组中[0, i - 1]的和,然后我们对于sums中每一个值sums[i],用二分查找法找到子数组的右边界位置,使该子数组之和大于sums[i] + s,然后我们更新最短长度的距离即可。

自己当时用的唯一不同是sums数组并没有比原来长一位,sums[i]表示sums数组中[0,i]的和。

class Solution {
public:
        int minSubArrayLen(int s, vector<int>& nums) {
                int len=nums.size();
                if(len==0) return 0;
                int MinLength;
                int sum=0;
                //如果所有的值加起来都小于s,就没有继续下去的必要了
                for(int i=0;i<len;i++){
                        sum+=nums[i];
                        if(sum>=s) break;
                }
                if(sum>=s){
                        MinLength=len;
                }else{
                        return 0;
                }


                //前面所有元素累加的数组
                int* all=new int[len];
                all[0]=nums[0];
                for(int i=1;i<len;i++){
                        all[i]=all[i-1]+nums[i];
                }
                //以第一个元素作为左边界,确定大于s的最小右边界
                int left=0,right=len-1;
                int mid;
                if(all[right]<s){
                        delete []all;
                        return 0;
                }
                while(left<right){
                        mid=(left+right)/2;
                        if(all[mid]<s){
                                left=mid+1;
                        }else{
                                right=mid;
                        }
                }
                if(MinLength>right-0+1){
                        MinLength=right-0+1;
                }
                //以第当前元素作为左边界,确定大于s的最小右边界
                for(int i=1;i<len;i++){
                        left=i,right=len-1;
                        if(all[right]-all[left-1]<s) continue;
                        while(left<right){
                                mid=(left+right)/2;
                                if(all[mid]-all[i-1]<s){
                                        left=mid+1;
                                }else{
                                        right=mid;
                                }
                        }
                        if(MinLength>right-i+1){
                                MinLength=right-i+1;
                        }
                }
                delete []all;
                return MinLength;
        }
};