JunyiCode
4/21/2020 - 1:15 AM

209. Minimum Size Subarray Sum

2 pointers binary search

/*
ans = min(ans, (j - i + 1));
    Found the smallest subarray with sum>=s starting with index i, hence move to next index
    we can't find a shorter subarray that starts at i
    
*/

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int minLen = Integer.MAX_VALUE;
        for (int i = 0; i < nums.length; i++){
            int sum = 0;
            for (int j = i; j < nums.length; j++) {
                sum += nums[j];
                if (sum >= s){
                    minLen = Math.min(minLen, j - i + 1);
                    break;  
                }
            }
        }
        
        return minLen == Integer.MAX_VALUE ? 0 : minLen;
    }
}


class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int n = nums.length;
        int ans = Integer.MAX_VALUE;
        int left = 0;
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += nums[i];
            while (sum >= s) {
                ans = Math.min(ans, i + 1 - left);
                sum -= nums[left++];
            }
        }
        
        return (ans != Integer.MAX_VALUE) ? ans : 0;
    }
}
/*
  ⭐️sums[]其实就是sorted array,所以可以用bs
  while(i < j)判断最后整个subarray的sum都小于s的情况和上面的条件不一样,因为i和j都指向最后一位,最后j = nums.length
  if (j == nums.length)   break;
*/

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int sum = 0;
        int min = Integer.MAX_VALUE;
        int[] sums = new int[nums.length];
        
        for(int i = 0; i < nums.length; i++) {
            if(i == 0) {
                sums[i] = nums[i];
            } else {
                sums[i] = nums[i] + sums[i - 1];
            }
        }
        
        for (int i = 0; i < nums.length; i++) {
            int j = findWindowEnd(i, sums, s);
            if (j == nums.length) 
                break;
            min = Math.min(j - i + 1, min);
        }
        
        return min == Integer.MAX_VALUE ? 0 : min;
    }
    
    private int findWindowEnd(int start, int[] sums, int s) {
        int i = start, j = sums.length - 1;
        int offset = start == 0 ? 0 : sums[start - 1];
        
        while(i <= j) {
            int mid = i + (j - i) / 2;
            int sum = sums[mid] - offset;
            if(sum >= s) {
                j = mid - 1;
            } else {
                i = mid + 1;
            }    
        }
        
        return i;
    }
}
/*
  ⭐️sums[]其实就是sorted array,所以可以用bs
  while(i < j)判断最后整个subarray的sum都小于s的情况和上面的条件不一样,因为i和j不能都指向最后一位
    if(sums[j] - offset < s)  return -1;
  
*/

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int sum = 0;
        int min = Integer.MAX_VALUE;
        int[] sums = new int[nums.length];
        
        for(int i = 0; i < nums.length; i++) {
            if(i == 0) {
                sums[i] = nums[i];
            } else {
                sums[i] = nums[i] + sums[i - 1];
            }
        }
        
        for (int i = 0; i < nums.length; i++) {
            int j = findWindowEnd(i, sums, s);
            if (j == -1) 
                break;
            min = Math.min(j - i + 1, min);
        }
        
        return min == Integer.MAX_VALUE ? 0 : min;
    }
    
    private int findWindowEnd(int start, int[] sums, int s) {
        int i = start, j = sums.length - 1;
        int offset = start == 0 ? 0 : sums[start - 1];
        if(sums[j] - offset < s)  return -1;
        
        while(i < j) {
            int mid = i + (j - i) / 2;
            int sum = sums[mid] - offset;
            if(sum >= s) {
                j = mid;
            } else {
                i = mid + 1;
            }    
        }
        
        return i;
    }
}