【Leetcode递增子序列】300. 最长递增子序列(子序列不连续) NC91最长上升子序列(三)(子序列不连续) 674. 最长连续递增序列(子序列连续)



Leetode300(子序列不连续)

1.问题描述

在这里插入图片描述

2.解决方案

在这里插入图片描述

代码sxl上有详细解答,这只做强调
1.犯了一个不过脑子错误,最后要求的值不一定处在那个序列范围中,所以其实是dp[0]…dp[len-1]中的最大值,而不是dp[len-1]
2.初始化都是1
3.递推也不错多看一看

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        //1.
        int len=nums.size();

        //2.
        vector<int> dp(len,1);

        //3.
        int ans=-1;
        for(int i=0;i<len;i++){
            for(int j=0;j<i;j++){
                if(nums[j]<nums[i]){
                    dp[i]=max(dp[i],dp[j]+1);
                }
            }
            ans=max(ans,dp[i]);
        }

        //4.
        //return dp[len-1]; 没过脑子错误
        return ans;
    }
};
class Solution {
    public int lengthOfLIS(int[] nums) {
        //1.
        int len = nums.length;
        int[] dp = new int[len];
        Arrays.fill(dp, 1);

        //2.
        for(int i=0;i<len;i++){
            int max = -1;
            boolean isMax = false;
            for(int j=0;j<i;j++){
                if(nums[j]<nums[i]){
                    isMax = true;
                    max = Math.max(max, dp[j]);
                }
            }
            if (isMax){
                dp[i]=max+1;
            }
        }

        //3.
        int res = -1;
        for(int i=0;i<len;i++){
            res = Math.max(res, dp[i]);
        }
        return res;
    }
}


NC91(子序列不连续)

1.问题描述

题目链接

在这里插入图片描述

2.解决方案

解法一:动态规划(超时)

和上一题300,解法一模一样,这个向前查询的思路也很巧妙,需要关注一下,因为最小的数往往在后面

在这里插入图片描述

import java.util.*;


public class Solution {
    public int[] LIS (int[] arr) {
        //1.
        int len = arr.length;
        int[] dp = new int[len];
        Arrays.fill(dp, 1);
        int max = -1;
        for(int i=0;i<len;i++){
            for(int j=0;j<i;j++){
                if(arr[j]<arr[i]){
                    dp[i] = Math.max(dp[i], dp[j]+1);
                    max = Math.max(max, dp[i]);
                }
            }
        }
        //2.
        int[] ans = new int[max];
        for(int i=len-1, j=max-1;j>=0;i--){
            if(dp[i]==max){
                ans[j] = arr[i];
                j--;
                max--;
            }
        }
        return ans;
    }
}


解法二:动态规划+二分

在这里插入图片描述

class Solution {
public:
    vector<int> LIS(vector<int>& arr) {
        int n = arr.size();
        vector<int> d(n + 1, -1), p(n);
        int len = 1;//初始化长度为1,元素为序列第一个数字
        d[len] = arr[0];
        p[0] = 1;
        for(int i = 1; i < n; ++i) {
            if(arr[i] > d[len]) {
                //此时将该数字添加到末尾
                d[++len] = arr[i];
                p[i] = len;
            } else {
                //二分查找恰好合适的位置
                int left = 1, right = len, pos = 0;
                while(left <= right) {
                    int mid = (left + right) / 2;
                    if(d[mid] < arr[i]) {
                        pos = mid;
                        left = mid + 1;
                    } else {
                        right = mid - 1;
                    }
                }
                //对该位置数字进行更新
                d[pos + 1] = arr[i];
                p[i] = pos + 1;
            }
        }
        vector<int> ans(len);
        //逆向查找对应序列值
        for(int i = n - 1; i >= 0; --i) {
            if(p[i] == len) {
                ans[--len] = arr[i];
            }
        }
        return ans;
    }
};


Leetode674(子序列连续)

1.问题描述

在这里插入图片描述

2.解决方案

代码sxl上有详细过程,这只做强调
1.dp[i]含义应该是以i结尾的最长长度
2.初始化都是1
3.递推就按照题意想出
4.一个没考虑周全的错误,初始化了ans=-1,这是如果len==1的数组for循环会直接被跳过,拿结果就变成了-1,既然我们把过程分析的很清楚了,那就大胆一点就是1,因为最小值就是1

在这里插入图片描述

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        //1.
        int len=nums.size();
        
        //2.
        vector<int> dp(len,1);
        
        //3.
        int ans=1;
        for(int i=1;i<len;i++){
            if(nums[i-1]<nums[i]) 
                dp[i]=max(dp[i],dp[i-1]+1);
            ans=max(ans,dp[i]);
        }
        
        //4.
        return ans;
    }
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值