LeetCode 209. Minimum Size Subarray Sum ?

Tech In Pieces發表於2020-11-10

given an array and a positive integer s, we have to find the shortest subarray such that the sum of its element >= s.

the first thought in my mind is maintain a sliding windows, and always have the minimum length;

I was trying to solve it using sliding window:
但是下面的程式碼怎麼搞都不對

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int i = 0;
        int j = 0;
        int min = Integer.MAX_VALUE;
        int sum = 0;
        while (j < nums.length) {
            while (j < nums.length - 1 && sum < s) {
                sum += nums[j++];
            }
            while (sum >= s) {
                sum -= nums[i++];
            }
            min = Math.min(min, j - i + 2); //j stoped at the posistion makes sum>=s, and i stopped at the position where makes sum<s, so i should be in the position of i-1, and [i-1, j] should be the right position
            j++;
        }
        return min == Integer.MAX_VALUE? 0: min;   
    }
}
class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int i = 0;
        int j = 0;
        int min = Integer.MAX_VALUE;
        int sum = 0;
        while (j < nums.length) {
            sum += nums[j];
            if (sum < s) {
                j++;
                continue;
            }
            while (sum >= s) {
                sum -= nums[i++];
            }
            min = Math.min(min, j - i + 2);
            j++;
        }
        return min == Integer.MAX_VALUE? 0: min;   
    }
}

同時 這個題目還跟二分法有關。
那麼是怎麼樣跟二分法有關呢?看起來牛風馬不相及的事情。而且原陣列還沒有排序 當然也不能排序。
回憶一下我們如何快速計算sunarray和或者乘積
對了!就是用prefix sum/multiple.
但是就算這樣也不能想出來怎麼樣才能檢索和大於s的子陣列。
所以在下面的程式碼裡面:
for (int i = 0; i < sums.length; i++) {
int end = binarySearch(i + 1, sums.length - 1, sums[i] + s, sums); //this binary search get the first one which subarray sum larger or equals to s.
}

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int[] sums = new int[nums.length + 1];
        
        for (int i = 1; i < sums.length; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        int minLen = Integer.MAX_VALUE;
        for (int i = 0; i < sums.length; i++) {
            int end = binarySearch(i + 1, sums.length - 1, sums[i] + s, sums); //trying to find the subarray between i+1 and the end which the sum>=s. we have to find the first that satisfy this need so that makes shorter
            if (end == sums.length) break; //if we can't find any, then it means that even we added tham all, the sum still less than s, there is no need to search more, just break.
            if (end - i < minLen) minLen = end - i; //update minLen if necessary
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen;
    }
    
    private int binarySearch(int lo, int hi, int target, int[] sums) { //find the target between sums[lo, hi], if not trying to get the first one that is larger than it
        while (lo <= hi) {
            int mid = (hi - lo) / 2 + lo;
            if (sums[mid] == target) {
                return mid;
            } else if (sums[mid] > target) {
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
        }
        return lo;
    }
}

相關文章