最长递增子序列的两种解法

以LeetCode-300为例:

O(n^2)解法:

dp数组表示以i结尾的最长递增子序列的长度

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

O(nlogn)解法:

tails[i]数组定义:长度为i+1最长递增子序列的最小值末尾值

以nums[4,5,6,3]为例

len = 1   :      [4], [5], [6], [3]   => tails[0] = 3
len = 2   :      [4, 5], [5, 6]       => tails[1] = 5
len = 3   :      [4, 5, 6]            => tails[2] = 6
很容易判断tails数组递增,可以应用二分法
(1) if x is larger than all tails, append it, increase the size by 1
(2) if tails[i-1] < x <= tails[i], update tails[i]
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> tails(nums.size(),0);
        int size=0;
        for(int t=0;t<nums.size();t++)
        {
            int i=0,j=size;
            while(i!=j)
            {
                int mid=(i+j)/2;
                if(tails[mid]<nums[t])i=mid+1;
                else j=mid; // 注意这里为了取到右端的值
            }
            tails[i]=nums[t];
            if(i==size)size++;
        }
        return size;
    }
};
posted @ 2017-05-18 20:08  demianzhang  阅读(566)  评论(0编辑  收藏  举报