leetcode300. 最長上升子序列升子序列

給定一個無序的整數數組,找到其中最長上升子序列的長度。

輸入: [10,9,2,5,3,7,101,18]
輸出: 4 
解釋: 最長的上升子序列是 [2,3,7,101],它的長度是 4

1,動態規劃,(本題動態規劃是比較好理解的,但顯然效率比較低)

int lengthOfLIS(vector<int>& nums) {
        int len=nums.size();
        int maxlen=0;
        //if(len==0) return 0;
        //if(len==1) return 1;
        vector<int> dp(len,1)for(int i=0;i<len;i++){
            for(int j=0;j<i;j++){
                if(nums[j]<nums[i])
                    dp[i]=max(dp[i],dp[j]+1);           
                                  
            }
            maxlen=max(maxlen,dp[i]); 
        }
        return maxlen;
    }

dp[i] 表示以 nums[i] 這個數結尾的最長遞增子序列的長度。
當時作此題時,dp數組習慣初始化爲0.,結果一直不對,比結果少一,。後來參考了,才知道**dp需要初始化爲1,**這樣進行理解,不管整體結果,本身當前值就是一個最小子序列,長度爲1。
時間複雜度 O(N^2)。

2,二分查找(真的很難想到,也不好理解)(在安利一次啊,不明白流程如何操作循環的,去debug一下l)
紙牌方法解釋此題

在這裏插入圖片描述
每次處理一張撲克牌不是要找一個合適的牌堆頂來放嗎,牌堆頂的牌不是有序嗎,這就能用到二分查找了:用二分查找來搜索當前牌應放置的位置。

int lengthOfLIS(vector<int>& nums) {
        int len=nums.size();
        vector<int> res(len);
        int maxlen=0;
        //for(int num : nums){
           //int num=nums[i];
           
        //按照左側邊界進行二分查找
        for(int i=0;i<len;i++){
            //要處理的撲克牌
           
            int left=0,right=maxlen;
            while(left<right){
                int mid=(left+right)/2;
                if(res[mid]<nums[i])
                    left=mid+1;
                else
                    right=mid;
            }
            /*********************************/
        
            // 沒找到合適的牌堆,新建一堆
            if(maxlen==left)
                maxlen++;
                // 把這張牌放到牌堆頂
            res[left]=nums[i];           
        }
        return maxlen;
    }
    int main() {
        vector<int> nums{ 6,3,5,10,11,2,9,14,13,7,4,8,12 };
        lengthOfLIS(nums);
        return 0;
    }

二分搜索

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