LeetCode/最大递增子序列

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

1. 动态规划

dp[i]表示以i结尾的最长长度
状态转移方程dp[i] = max(dp[j])+1 if num[j]<num[i]
边界条件 dp[0] = 1
时间复杂度为O(n2),即遍历一遍,同时对每个元素往前搜索一遍

动态规划
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        //动态规划
        int n = nums.size();
        if(n==0) return 0;
        vector<int> dp(n); //dp[i]表示以i结尾的最长长度
        int res = 0;
        for(int i=0;i<n;i++){
            int max_ = 0;
            for(int j=0;j<i;j++){
                if(nums[j]<nums[i]) max_=max(max_,dp[j]);
            }
            dp[i]= max_+1;
            res = max(res,dp[i]);
        }
        return res;
    }
};

2. 动态规划优化

注意到方法一反向搜索时,要找的是序列末位元素小于当前元素的最大序列长度
我们关心的只是某一序列长度的最小末尾元素,所以dp[i]可以表示为序列长度为i的最小末尾元素值
这样不仅能减少查找的数据量,还能使用二分法进行查找

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        //动态规划
        int n = nums.size();
        if(n==0) return 0;
        vector<int> dp(n); //dp[i]记录i长度序列的最后元素值
        int res = 0;
        for(int k=0;k<n;k++){
           int i =0;int j =res;//res 为当前最长长度
           while(i<j){
               int m = (i+j)/2;
               if(dp[m]<nums[k]) i=m+1;//移动左边界,最终移到恰满足条件的下一位置
               else j=m; //移动右边界
           }
           dp[i] = nums[k];//把该元素作为最小元素替换下一序列长度
            if(j==res) res++;//如果该位置拓宽了最大长度,最大长度更新
        }
        return res;
    }
};
posted @ 2022-06-05 20:25  失控D大白兔  阅读(30)  评论(0编辑  收藏  举报