• leetcode300.最长上升子序列


    给定一个无序的整数数组,找到其中最长上升子序列的长度。

    示例:

    输入: [10,9,2,5,3,7,101,18]
    输出: 4
    解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

    说明:

    可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
    你算法的时间复杂度应该为 O(n2) 。

    进阶:

    你能将算法的时间复杂度降低到 O(n log n) 吗?

    思路:维护一个tail数组,tail[k]表示长度为k+1的最长上升子序列的尾部元素例如:原数组为[10,9,2,5,3,7,21,18]

    tail每轮更新情况:
    i=0时:tails:[10]
    i=1时:tails:[9]
    i=2时:tails:[2]
    i=3时:tails:[2,5]
    i=4时:tails:[2,3]
    i=5时:tails:[2,3,7]
    i=6时:tails:[2,3,7,21]
    i=7时:tails:[2,3,7,18]
    每次都保持尾部元素最小。
    如果再加一个5元素,则通过二分法找到第一个大于5的元素7,将7替换成5。
    如果再加一个9元素,则通过二分法找到第一个大于9的元素18,将18替换成9。如此下去。
    因为题目要求将算法复杂度降到nlogn,而遍历数组中的数字是免不了的,只能优化tail的更新过程,我们可以看到tails中的元素必然是
    有序的,所以显然我们可以通过二分查找快速定位到需要替换的元素位置。代码如下:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> tails(nums.size());
        int res = 0;
        for(int num : nums) {
            int i = 0, j = res;
            //while循环退出条件:i == j
            while(i < j) {
                int mid = (i + j) / 2;
                if(num > tails[mid]) i = mid + 1;
                else j = mid; //此处不能是mid-1
            }
    
            tails[i] = num;
            //res == j表示j一直没有前移,一直指向最末尾,表示tail中所有数字都小于num,直接加到tails末尾
            if(res == j) res++;
        }
        return res;
    }
  • 相关阅读:
    iOS
    WKWebview 获取网页加载内容的高度
    iPhoneXS、XS Max与iPhoneXR 适配
    iOS:iPhone X,iPhone XS,iPhone XR,iPHone XS Max 适配
    git---全局设置用户名、密码、邮箱
    iOS 拖动手势(UIPanGestureRecognizer)
    ios 扩大button的点击区域
    iOS总结 | 修改button响应区域的各种姿势
    swift常用第三方库
    《从零开始学Swift》学习笔记(Day 33)——属性观察者
  • 原文地址:https://www.cnblogs.com/joker1937/p/12812892.html
Copyright © 2020-2023  润新知