leetcode 300. 最长上升子序列 O(nlogn)解法证明

原题: https://leetcode-cn.com/problems/longest-increasing-subsequence/

O(n^2)的做法不赘述, https://www.cnblogs.com/grandyang/p/4938187.html 提到了O(nlogn)的解法如下:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> v;
        for (auto a : nums) {
            auto it = lower_bound(v.begin(), v.end(), a);
            if (it == v.end()) v.push_back(a);
            else *it = a;
        }
       return v.size();
    }
};

解法遍历了数组nums, 并维护了一个辅助数组, 本文将阐述辅助数组的定义, 以及其有效性的证明.

辅助数组v的定义如下:

当算法遍历到第n个元素时, 辅助数组里的第i个元素的含义为:

  维护的是在第[0, n-1]个元素中, 要维护长度为i的递增子序列时, 结尾元素的最小值.

这个辅助数组v是递增的, 此处用反证法进行证明:

设辅助数组v有两个元素v[i]和v[j], i < j.

假如v[i] >= v[j], 则对于v[j]所对应的长度为j的递增序列, 其v[j-1]一定小于v[j], 于是有v[j-1] < v[j] <= v[i].

那么数组v的第i个元素值应当为v[j-1]了, 出现矛盾.

为什么要用lower_bound而不是upper_bound寻找替代点呢? 因为要维护辅助数组的递增特性, 如果用upper_bound取到的是大于遍历元素a的元素, 而在它之前有中有等于a的元素,则替换后会有两个等于a的元素, 破坏了递增的特性.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值