Leetcode 第209題:Minimum Size Subarray Sum--長度最小的子數組(C++、Python)

題目地址:Minimum Size Subarray Sum


題目簡介:

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

示例:

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

題目解析:

1、遞歸思路,但是內存錯誤(Memory Limit Exceeded):

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        self.size = len(nums)
        ans = self.size + 1
        for i in range(self.size):
            ans = min (ans, 1 + self.search(s - nums[i], nums[i + 1:]))
        return ans if ans <= self.size else 0
    
    def search(self, s, nums):
        if (s <= 0):
            return 0
        if (len(nums) == 0):
            return self.size + 1
        return self.search(s - nums[0], nums[1:]) + 1

2、暴力吧,計算每個小區間的總和,只要出現大於等於s,便更新最終結果。

C++:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        if (nums.empty())
            return 0;
        
        int _size = nums.size();
        int ans = _size + 1;
        for (int i = 0; i < _size; i++)
        {
            int tmp = 0;
            for (int j = i; j < _size;j++)
            {
                tmp += nums[j];
                if (tmp >= s)
                {
                    ans = min(j - i + 1, ans);
                    continue;
                }
            }
        }
        return ans <= _size ? ans : 0;
    }
};

3、但是需要考慮計算的複雜度,題目要求是要考慮到O(n)時間複雜度,那麼可以從全局的角度來看。

當最小區間內的數字加起來大於等於目標值後,那麼再加上額外的數字也是大於目標值。那麼反過來想,先確定一個肯定大於當前目標值的區間,逐漸縮小這個區間,並且需要滿足縮小後的區間的總和任然大於目標值。

使用雙指針,先移動右指針,找到合適的區間。然後逐漸縮小左指針,確定一個最小的區間。如此當左指針和右指針都達到最右端時,遍歷完成。時間複雜度O(2n)。

C++:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        if (nums.empty()) 
            return 0;
        int _size = nums.size();
        int ans = _size + 1;
        
        int left = 0, right = 0, sum = 0;
        while (right < _size) 
        {
            while (sum < s && right < _size) 
            {
                sum += nums[right++];
            }
            while (sum >= s) 
            {
                ans = min(ans, right - left);
                sum -= nums[left++];
            }
        }
        return ans <= _size + 1 ? 0 : ans;
    }
};

Python:

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        _size = len(nums)
        ans = _size + 1
        
        left = 0
        right = 0
        total = 0
        while (right < _size):
            while (total < s and right < _size):
                total += nums[right]
                right += 1
                
            while (total >= s):
                ans = min(ans, right - left)
                total -= nums[left]
                left += 1
                
        return ans if ans < _size + 1 else 0

4、二分轉載地址

C++:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        if (nums.empty())
            return 0;
        int n = nums.size();
        int ans = n + 1;
        vector<int> sums(n + 1, 0);
        for (int i = 1; i < n + 1; ++i) 
            sums[i] = sums[i - 1] + nums[i - 1];
        for (int i = 0; i < n; i++) 
        {
            int left = i + 1, right = n, t = sums[i] + s;
            while (left <= right) 
            {
                int mid = left + (right - left) / 2;
                if (sums[mid] < t) 
                    left = mid + 1;
                else 
                    right = mid - 1;
            }
            if (left == n + 1) 
                break;
            ans = min(ans, left - i);
        }
        return ans == n + 1 ? 0 : ans;
    }
};

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章