最长递增子序列(LIS) 贪心+二分详解O(nlogn)

Posted C_YCBX Py_YYDS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长递增子序列(LIS) 贪心+二分详解O(nlogn)相关的知识,希望对你有一定的参考价值。

从递增的三元序列引进贪心

题目

在这里插入图片描述
oj平台

O(N)贪心解法

这种O(n)的方法妙处在于:我们不需要关心这三个数字的相对位置,只管更新长度为1、2的递增序列的结尾的最小数字,一旦遇上比长度为2的最小结尾数字要大的,则必出现递增的三元递增序列。


class Solution {
public:
    bool increasingTriplet(vector<int>& nums) {
        //用于更新长度为1的递增序列的最小尾数,以及长度为2的递增序列的最小尾数
        int first = INT_MAX;
        int second = INT_MAX;
        for (int t : nums) {
            //更新第一小的数字
            if (t <= first) {
                first = t;
            } else if (t <= second) {
                //更新第二小的数字(因为只有比第一小的数字大才能走到这一步)
                second = t;
            } else {
                //一旦前面两步都没执行,比前面两个都大的数字出现了
                return true;
            }
        }
        return false;
    }
};

最长递增子序列(LIS)的贪心+二分解法

题目

在这里插入图片描述
oj平台

贪心+二分详解

首先我们如果要实现二分过程,那么就必须保证过程中所保存的数据是要有序的,而如果用 LCS 的方法进行变种,则不可能保证有序,所以我们另想办法进行有序处理,我们如上一种题目一样,把 dp[i] 记录长度为 i+1 递增序列的结尾最小元素,比如 1,2,1,3 中长度为2的最小结尾元素对应:dp[1] = 2,对应序列:1,2.

  • 对应的动画更新过程:
    在这里插入图片描述

这样便保证了每次查找的对象是有序的,便可以用二分进行查找优化了。

  • 效率差距如此之大!
    在这里插入图片描述
    在这里插入图片描述
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int>dp(nums.size(),0);
        int end = 1;
        dp[0] = nums[0];
//寻找上边界的二分,我选择的是左闭右开的方式,注意如果存在相同元素,则直接不能算作一个长度
       for(int i=1;i<nums.size();i++){
           int l=0,r=end;
           int target=nums[i];
           while(l<r){
               int mid = (l+r)/2;
               if(dp[mid]>target)
                    r = mid;
                else if(dp[mid]<target)
                    l = mid+1;
                else{
                    l = mid;
                    break;
                }
           }
           dp[l] = target;
           //注意更新右边界
           if(l==end)
            end++;
       }
    
       return end;
    }
};

以上是关于最长递增子序列(LIS) 贪心+二分详解O(nlogn)的主要内容,如果未能解决你的问题,请参考以下文章

LIS 最长上升子序列问题(动态规划贪心+二分)

LIS 最长上升子序列问题(动态规划贪心+二分)

最长递增子序列 LIS 时间复杂度O(nlogn)的Java实现

[Mdp] lc673. 最长递增子序列的个数(LIS+算法优化+算法拓展)

[Mdp] lc673. 最长递增子序列的个数(LIS+算法优化+算法拓展)

[Mdp] lc673. 最长递增子序列的个数(LIS+算法优化+算法拓展)