程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> [LeetCode從零單刷]Longest Increasing Subsequence

[LeetCode從零單刷]Longest Increasing Subsequence

編輯:關於C++

題目:

 

Given an unsorted array of integers, find the length of longest increasing subsequence.

For example, Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

解答:

尋找最長上升子序列(LIS),最基本的方法是動態規劃。轉移方程為 dp[i] = max{dp[j]} + 1 ( -1< j < i && nums[j] < nums[i])。

解釋也非常直觀:dp[i] 表示如果取得當前 i 元素,所能達到的最長 LIS。如果需要打印出此序列,僅需要保存上一個元素。

 

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

 

如果要修改到 O(n log n) time complexity?貪心法 + 二分搜索

增加一條輔助的順序(ordered)棧(隊列……完成任務就好),保存盡可能長的LIS。入棧的要求為:

將a[0]入棧每次取棧頂元素top(最大元素)和讀到的元素a[i](0 top 則將a[i]入棧;- 如果a[i] <= top則二分查找棧中的比a[i]大的第1個數,並用a[i]替換它(如果棧頂元素被替換,說明有機會到達更長序列);最長序列長度即為棧的大小

 

直觀理解:對於 x 和 y,如果 x < y 且 stack[y] < stack[x],用 stack[x] 替換 stack[y],此時的最長序列長度沒有改變,但序列繼續變長的''潛力''增大,這就是貪心的目標。

舉例:原序列為1,5,8,3,6,7

開始1,5,8相繼入棧,此時讀到3,用3替換5,得到1,3,8;再讀6,用6替換8,得到1,3,6;再讀7,得到最終棧為1,3,6,7。最長遞增子序列為長度4

但是這個方法,有一個很大的缺陷:只能保證序列長度的正確性,不能保證棧中就是正確的序列

舉例:原序列為1,5,8,2,棧內最後是 1,2,8 不是正確的序列。

分析一下,我們可以看出,雖然有些時候這樣得不到正確的序列,但最後算出來的個數是沒錯的,為什麼呢?

當a[i]>top時,總個數直接加1,這肯定沒錯;但當a[i]

 

class Solution {
public:
    int lengthOfLIS(vector& nums) {
        vector LIS;
        for (int i = 0; i < nums.size(); i++) {
            if (LIS.size() == 0 || LIS[LIS.size() - 1] < nums[i]) {
                LIS.push_back(nums[i]);
            }
            else {
                int l = 0, r = LIS.size() - 1;
                while (l < r) {
                    int m = (l + r) / 2;
                    if (LIS[m] >= nums[i]) {
                        r = m;
                    }
                    else {
                        l = m + 1;
                    }
                }
                LIS[l] = nums[i];
            }
        }
        return LIS.size();
    }
};

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved