300. 最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:

输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:

输入:nums = [7,7,7,7,7,7,7]
输出:1

解析:

用当前状态的思想,该状态能否可以由前面状态推出来。

写出递推式,定义下角标的含义:

我们从小到大计算 dp数组的值,在计算 dp[i]之前,我们已经计算出 dp[0…i−1]的值,则状态转移方程为:dp[i]=max⁡(dp[j])+1,其中 0≤j

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

第二种解法是用二分查找:

class Solution {
public:
    int lengthOfLIS(vector& nums) {
        int  len = 1,n = nums.size();
        if(n == 0){
            return 0;
        }
        vector d(n+1,0); // 记录最长升序数组
        d[len] = nums[0];
        for(int i= 1;i  d[len]){
                d[++len] = nums[i];
            }else{
                int l = 1,r = len,pos = 0;
                while(l <= r){
                    int mid =(l + r) >>1;
                    if(d[mid] < nums[i]){
                        pos = mid;
                        l =mid + 1;
                    }else{
                        r = mid -1;
                    }
                }
                d[pos+1] = nums[i];
            }
        }
    }
};

你可能感兴趣的:(算法)