leetcode【300】【tag DP Binary Search】Longest Increasing Subsequence【c++版本,时间95%,二分查找】

问题描述:

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

Example:

Input: [10,9,2,5,3,7,101,18]
Output: 4 
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4. 

Note:

  • 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?

源码:

这题的tag是动态规划,我就不展示其他的做法,直接上动态规划。

首先看一下我自己的菜鸡思路,我用dp[i]表示以i为结尾的最长的递增序列长度(必须包含元素i)。那么递归方程可以写成如下格式:

dp[i] = max(dp[j]+1) ,其中j<i且nums[i]>nums[j]

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

看了一下solution有个基于二分查找的方法,英文的我也没大看懂,还是翻了一下别人的博客。

dp[i]: 长度为i + 1的上升子列的结尾元素的最小值
遍历nums的每个元素,逐个与dp数组比较,更新dp数组中的元素或增长dp数组
更新的算法是:对于nums中的元素target,找到dp中大于等于target的最小元素,更新之;若target大于dp中最后一个元素,则将target置于dp后面一个位置,并增长dp
最终dp数组的长度就是nums的最大上升子列的长度
易证dp是一个单调递增数列,因此更新算法的查找过程可以用O(logn)的时间复杂度完成

时间95%,空间66%

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size(), result = 1;
        if (n==0)   return 0;
        vector<int> dp;
        dp.push_back(nums[0]);
        for (int i=1; i<n; i++){
            if (dp.back() < nums[i]){
                dp.push_back(nums[i]);
            }
            else {
                *lower_bound(dp.begin(), dp.end(), nums[i]) = nums[i];
            }
        }
        return dp.size();
    }
};

其中Low_bound就是找大于等于目标值的最小值的位置

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