[dp]leetcode300:最长上升子序列(medium)

题目:
在这里插入图片描述
题解:

  • 思路1:动态规划,时间复杂度O(n2),空间复杂度为O(n)。
  • 状态:dp[i]表示以nums[i]结尾的最长上升子序列的长度
  • 状态转移方程:dp[i]=max(dp[i],dp[j]+1)。设j∈[0,i),考虑每轮计算新dp[i]时,遍历[0,i)列表区间。若nums[j]<nums[i],那么dp[i]=max(dp[i],dp[j]+1);否则dp[i]不变。

  • 思路2:动态规划+二分查找,时间复杂度O(nlogn),空间复杂度O(n)。
  • 思路2是思路1的优化,计算每个dp值需要O(n)的时间复杂度,二分查找num需要O(logn)的时间复杂度。
  • 遍历nums,我们需要找到大于等于num的最小值的位置idx。若idx大于等于dp数组的大小,则表示我们需要将num添加到dp后面,这样可维持上升子序列的增长;若idx小于dp数组的大小,则表示我们需要更新dp[idx]的值,这样可保证上升子序列中每个值相对较小。

代码如下:

class Solution {
public:
    //题解1:动态规划,dp[i]表示以nums[i]结尾的最长上升子序列的长度
    //状态转移方程:设j∈[0,i),考虑每轮计算新dp[i]时,遍历[0,i)列表区间。若nums[j]<nums[i],那么dp[i]=max(dp[i],dp[j]+1);否则dp[i]不变
    int lengthOfLIS_1(vector<int>& nums) {
        int n=nums.size(),res=0;
        vector<int> dp(n,1);
        for(int i=0;i<n;++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;
    }

    //题解2:动态规划+二分查找
    int lengthOfLIS(vector<int>& nums){
        /*vector<int> dp(nums.size(),0);
        //res为最长上升子序列的长度
        int res=0;
        for(int &num:nums){
            //二分法:找到大于等于num的最小值dp[left]
            int left=0,right=res;
            while(left<right){
                int mid=left+((right-left)>>1);
                if(dp[mid]>=num)right=mid;
                else left=mid+1;
            }
            //更新dp[left]为nums,这样可保证left位置的值在当前上升子序列中最小
            dp[left]=num;
            //若res和left相等,即num大于res中的最大元素,所以num需要添加在res的后面,此时res需要+1
            if(res==left)res++;
        }
        return res;*/
        //换一种写法,与上面思路代码更接近
        if(nums.size()<2)return nums.size();
        vector<int> dp;
        for(int &num:nums){
            //二分法寻找大于等于num的最小值的位置,若该位置大于等于size,那么我们需要将num添加在dp尾部;否则更新idx的值,保证idx的值是最小的
            auto idx=lower_bound(dp.begin(),dp.end(),num)-dp.begin();
            if(idx>=dp.size())dp.emplace_back(num);
            else dp[idx]=num;
        }
        return dp.size();
    }
};
发布了512 篇原创文章 · 获赞 175 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_43152052/article/details/104090137
今日推荐