1. 程式人生 > >LeetCode 209. 長度最小的子陣列 Minimum Size Subarray Sum

LeetCode 209. 長度最小的子陣列 Minimum Size Subarray Sum

3-7 滑動視窗 Minimum Size Subarray Sum

題目:LeetCode 209. 長度最小的子陣列

給定一個含有 n 個正整數的陣列和一個正整數 s ,找出該陣列中滿足其和 ≥ s 的長度最小的連續子陣列。如果不存在符合條件的連續子陣列,返回 0。

示例:

輸入: s = 7, nums = [2,3,1,2,4,3] 輸出: 2 解釋: 子陣列 [4,3] 是該條件下的長度最小的連續子陣列。 進階:

如果你已經完成了O(n) 時間複雜度的解法, 請嘗試 O(n log n) 時間複雜度的解法。

// 209. Minimum Size Subarray Sum
// https://leetcode.com/problems/minimum-size-subarray-sum/description/
// // 暴力解法 // 該方法在 Leetcode 中會超時! // 時間複雜度: O(n^3) // 空間複雜度: O(1) public class Solution1 { public int minSubArrayLen(int s, int[] nums) { if(s <= 0 || nums == null) throw new IllegalArgumentException("Illigal Arguments"); int res = nums.length + 1; for(int l = 0 ; l <
nums.length ; l ++) for(int r = l ; r < nums.length ; r ++){ int sum = 0; for(int i = l ; i <= r ; i ++) sum += nums[i]; if(sum >= s) res = Math.min(res, r - l + 1); } if
(res == nums.length + 1) return 0; return res; } public static void main(String[] args) { int[] nums = {2, 3, 1, 2, 4, 3}; int s = 7; System.out.println((new Solution1()).minSubArrayLen(s, nums)); } }
// 209. Minimum Size Subarray Sum
// https://leetcode.com/problems/minimum-size-subarray-sum/description/
//
// 優化暴力解
// 時間複雜度: O(n^2)
// 空間複雜度: O(n)
public class Solution2 {

    public int minSubArrayLen(int s, int[] nums) {

        if(s <= 0 || nums == null)
            throw new IllegalArgumentException("Illigal Arguments");

        // sums[i]存放nums[0...i-1]的和
        int[] sums = new int[nums.length + 1];
        sums[0] = 0;
        for(int i = 1 ; i <= nums.length ; i ++)
            sums[i] = sums[i-1] + nums[i-1];

        int res = nums.length + 1;
        for(int l = 0 ; l < nums.length ; l ++)
            for(int r = l ; r < nums.length ; r ++){
                // 使用sums[r+1] - sums[l] 快速獲得nums[l...r]的和
                if(sums[r+1] - sums[l] >= s)
                    res = Math.min(res, r - l + 1);
            }

        if(res == nums.length + 1)
            return 0;

        return res;
    }

    public static void main(String[] args) {

        int[] nums = {2, 3, 1, 2, 4, 3};
        int s = 7;
        System.out.println((new Solution2()).minSubArrayLen(s, nums));
    }
}

// 209. Minimum Size Subarray Sum
// https://leetcode.com/problems/minimum-size-subarray-sum/description/
//
// 滑動視窗的思路
// 時間複雜度: O(n)
// 空間複雜度: O(1)
public class Solution3 {

    public int minSubArrayLen(int s, int[] nums) {

        if(s <= 0 || nums == null)
            throw new IllegalArgumentException("Illigal Arguments");

        int l = 0 , r = -1; // nums[l...r]為我們的滑動視窗
        int sum = 0;
        int res = nums.length + 1;

        while(l < nums.length){   // 視窗的左邊界在陣列範圍內,則迴圈繼續

            if(r + 1 < nums.length && sum < s)
                sum += nums[++r];
            else // r已經到頭 或者 sum >= s
                sum -= nums[l++];

            if(sum >= s)
                res = Math.min(res, r - l + 1);
        }

        if(res == nums.length + 1)
            return 0;
        return res;
    }

    public static void main(String[] args) {

        int[] nums = {2, 3, 1, 2, 4, 3};
        int s = 7;
        System.out.println((new Solution3()).minSubArrayLen(s, nums));
    }
}
// 209. Minimum Size Subarray Sum
// https://leetcode.com/problems/minimum-size-subarray-sum/description/
//
// 另外一個滑動視窗的實現, 僅供參考
// 時間複雜度: O(n)
// 空間複雜度: O(1)
public class Solution4 {

    public int minSubArrayLen(int s, int[] nums) {

        if(s <= 0 || nums == null)
            throw new IllegalArgumentException("Illigal Arguments");

        int l = 0 , r = -1; // [l...r]為我們的視窗
        int sum = 0;
        int res = nums.length + 1;

        while(r + 1 < nums.length){   // 視窗的右邊界無法繼續擴充套件了, 則迴圈繼續

            while(r + 1 < nums.length && sum < s)
                sum += nums[++r];

            if(sum >= s)
                res = Math.min(res, r - l + 1);

            while(l < nums.length && sum >= s){
                sum -= nums[l++];
                if(sum >= s)
                    res = Math.min(res, r - l + 1);
            }
        }

        if(res == nums.length + 1)
            return 0;
        return res;
    }

    public static void main(String[] args) {

        int[] nums = {2, 3, 1, 2, 4, 3};
        int s = 7;
        System.out.println((new Solution4()).minSubArrayLen(s, nums));
    }
}
// 209. Minimum Size Subarray Sum
// https://leetcode.com/problems/minimum-size-subarray-sum/description/
//
// 二分搜尋
// 擴充套件 Solution2 的方法。對於每一個l, 可以使用二分搜尋法搜尋r
//
// 時間複雜度: O(nlogn)
// 空間複雜度: O(n)
public class Solution5 {

    public int minSubArrayLen(int s, int[] nums) {

        if(s <= 0 || nums == null)
            throw new IllegalArgumentException("Illigal Arguments");

        // sums[i]存放nums[0...i-1]的和
        int[] sums = new int[nums.length + 1];
        sums[0] = 0;
        for(int i = 1 ; i <= nums.length ; i ++)
            sums[i] = sums[i-1] + nums[i-1];

        int res = nums.length + 1;
        for(int l = 0 ; l < nums.length - 1 ; l ++){
            // Java類庫中沒有內建的lowerBound方法,
            // 我們需要自己實現一個基於二分搜尋的lowerBound:)
            int r = lowerBound(sums, sums[l] + s);
            if(r != sums.length){
                res = Math.min(res, r - l);
            }
        }

        if(res == nums.length + 1)
            return 0;
        return res;
    }

    // 在有序陣列nums中尋找大於等於target的最小值
    // 如果沒有(nums陣列中所有值都小於target),則返回nums.length
    private int lowerBound(int[] nums, int target){

        if(nums == null /*|| !isSorted(nums)*/)
            throw new IllegalArgumentException("Illegal argument nums in lowerBound.");

        int l = 0, r = nums.length; // 在nums[l...r)的範圍裡尋找解
        while(l != r){
            int mid = l + (r - l) / 2;
            if(nums[mid] >= target)
                r = mid;
            else
                l = mid + 1;
        }

        return l;
    }

    private boolean isSorted(int[] nums){
        for(int i = 1 ; i < nums.length ; i ++)
            if(nums[i] < nums[i-1])
                return false;
        return true;
    }

    public static void main(String[] args) {

        int[] nums = {2, 3, 1, 2, 4, 3};
        int s = 7;
        System.out.println((new Solution5()).minSubArrayLen(s, nums));
    }
}