Leetcode 209. 長度最小的子數組(小白學習之路)

題目描述:

這個題目一開始我沒有看清題目中要求是“連續”的子數組,因此最早想到的方法是講整個數組排序,如果最大的數滿足>=s,則輸出1,最大加第二大的數滿足,則輸出2.遇到這個測試用例時報錯

s = 213, [12,28,83,4,25,26,25,2,25,25,25,12]

明確題意後,首先想到的方法是1.暴力法,兩個指針,遍歷幾乎所有情況,代碼如下:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) { 
        int slow=0,fast=0, minlen=10000,templen=255;    //一個慢指針一個快指針
        for(;slow<nums.size();slow++)     //慢指針從0開始
        {
            int sum=0;    //每開始一個慢指針,重置當前的和爲0
            for(fast=slow;fast<nums.size();fast++)    //快指針從慢指針開始往後加
            {
                sum+=nums[fast];
                if(sum>=s)    //滿足要求
                {
                    templen = fast- slow + 1;    //當前長度計算
                    if(templen<minlen) minlen=templen;     //如果小於最小長度,更新。這兩行可以用一行min函數的代碼搞定
                }
            }
        }
        if(templen==255) return 0;    //沒有滿足要求的情況,返回
        else return minlen;    

    }
};

看了下官方題解說的暴力法,時間複雜度有O(n3),我這種暴力法應該屬於改良過的,時間複雜度應該只有O(n2),測試結果從執行用時上看很慘淡,說明肯定有更好的方法;

第二種方法2.滑動窗口法

這種方法算法課上老師有提到過,這次終於碰到實戰應用,寫了一下確實很快,總的來說就是一前一後雙指針,形成了一個方框,所有的數加起來後如果<s,說明不存在滿足要求的數組,返回0;如果總和>=s,則加左指針可使總和減小,在此期間探到最小的數組長度,代碼如下:

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int left = 0, right = 0, sum = 0, minlen = 10000;
        while (left < nums.size()&& right<nums.size())
        {
            if (sum >= s)     //總和大於S的情況,左指針右移
            {
                minlen = min(minlen, right - left);
                sum -= nums[left];
                left++;
            }
            else    //總和小魚S的情況,右指針右移
            {
                sum += nums[right];  //先加右指針的數再把右指針右移,因此右指針屬於開區間
                right++;
            }

        }
        while (sum >= s&&left<nums.size())    //由於右指針開區間,存在越界風險,這裏討論的是已經加到最後一位的情況
        {
            minlen = min(minlen, right - left);
            sum -= nums[left];
            left++;
        }
        if (minlen == 10000) return 0;
        else return minlen;

    }
};

這裏的代碼可以再簡潔一點就是如果先加nums[right]再right++的話就不用擔心right越界的情況

 

還有第3中方法叫二分查找法,引進了一個新的sum數組,第i個數表示nums數組前i項的和,該方法我個人認爲比較複雜,將找最小數組的問題轉爲找一個臨界值的問題,從而可以用常用的更快的查找方法來加快速度,這裏就不寫了。

 

 

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