[leetcode 300] 最长上升子序列

问题描述

https://leetcode-cn.com/problems/longest-increasing-subsequence/
在这里插入图片描述

动态规划 O(n ^ 2)

动态规划的话,所使用的数组为 dp[len]

  • dp[i],表示从 原数组的 0 — 》 i 的所有数中,以 nums[i]结尾的最长递增子序列的长度

状态转移方程:

  • dp[i] = max(dp[ j ] + 1,dp [ i ]);,j —》 (0 --> i-1)

因为以每一个数为递增子序列的结尾数字时,当计算的时候,他的最后结果一定是由前面比他小的数字(n),以n结尾的最长递增子序列的长度 + 1得到的,也就是 dp[ j ] + 1

在初始化的时候,我们需要把每一个位置的长度都初始化为1,也就是以他本身结尾的最长递增子序列的长度最小是1

    int lengthOfLIS1(vector<int>& nums) 
    {
        int len = nums.size();
        if(len < 2) return len;

        vector<int> dp(len,1);

        for(int i = 1; i < len; i++)
            for(int j = 0; j < i; j++)
                if(nums[j] < nums[i])
                {
                    //当前的最长递增序列,一定是前面的一个比他小的数的长度 + 1变来的
                    dp[i] = max(dp[j]+1,dp[i]);
                }
        
        int ans = dp[0];
        for(auto& n : dp)
            ans = max(ans,n);
        return ans; 
    }

贪心 + 二分查找 O(n * log n)

在贪心的策略中,我们可以维护一个递增的数组,我们只要保证每次这个数组的末尾数字都是满足递增子序列要求的最小数字,那么我们下一次遍历的可能性就可以增加了

  • 每一次遍历的过程,我们需要找到第一个比当前数字(n)大的数字(m),然后用当前数字覆盖这个位置(m = n)
  • 如果当前数字比最后一个数字还大,那么直接在末尾插入就可以了
	int lengthOfLIS(vector<int>& nums)
    {
        int len = nums.size();
        if(len < 2) return len;

        vector<int> tail;
        int ans = 1;
        tail.push_back(nums[0]);

        for(auto& num : nums)
            if(num > tail[ans-1])   //数组中元素就是递增顺序的,如果比末尾元素大,就尾插
            {
                tail.push_back(num);
                ans++;
            }
            else 
            {
                //找到数组中第一个大于 num 的数字下标
                int le = 0;
                int ri = ans - 1;

                while(le < ri)
                {
                    int mid = (le + ri) / 2;
                    if(tail[mid] >= num) ri = mid;
                    else if(tail[mid] < num)   le = mid + 1;   
                }
                //num 覆盖这个数字
                tail[le] = num;
            }
        return ans;
    }

程序的过程

  1. 初始时的效果, i = 0 时

在这里插入图片描述

  1. i = 1

在这里插入图片描述

  1. i = 2

在这里插入图片描述

  1. i = 3

在这里插入图片描述

  1. i = 4

在这里插入图片描述

  1. i = 5

在这里插入图片描述

  1. i = 6

在这里插入图片描述

  1. i = 7

在这里插入图片描述

耗时比较

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值