Longest Increasing Subsequence

406 篇文章 0 订阅
406 篇文章 0 订阅

1,题目要求

Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.

Note:

  • There may be more than one LIS combination, it is only necessary for you to return the length.
  • Your algorithm should run in O(n2) complexity.
    Follow up: Could you improve it to O(nlogn) time complexity?

给定未排序的整数数组,找到最长的增加子序列的长度。

注意:

  • 可能有多个LIS组合,只需要您返回长度。
  • 您的算法应该以O(n 2)复杂度运行。
    跟进:你能把它提高到O(nlogn)时间复杂度吗?

2,题目思路

对于这道题,题目是一道比较经典的LIS问题,即最长上升子序列问题。

这种问题的解法很多,逐一说明太过麻烦。这里说一种利用C++内的STL的方法:lower_bound:

  • lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

在这道题的解法上,我们对定义的res数组利用lower_bound进行遍历,找到比nums[i]小的元素:

  • 如果找到,就将这个元素的值更新为nums[i];
  • 如果没找到,就说明此时的序列是递增的,则将这个nums[i]加入到res。

具体原理在于,在对nums的遍历的过程中,我们每次是找到res中第一个比nums[i]小的元素,之所以对它更新,是为了保证对之后新的res的创建。
当然,最后的结果中,res并不是正确的序列,但是长度是正确的。

为何是不正确的:(这里使用LeetCode的discussion的讲解)
For example, if

nums = [5,6,7,1,2,8,3,4,0,5,9]

then after we prcoess the 7:

S = [5,6,7]

after w process the 2:

S = [1,2,7]

after we process the 8:

S = [1,2,7,8]

Then we process the 3:

S = [1,2,3,8]

We process the 4:

S = [1,2,3,4]

and now the next three elements:

S = [0,2,3,4,5,9]

S is not the actual subsequence, but it is the right length (end ends in the right number).

而之所以最后的长度是可行的,是lower_bound是找到第一个比nums[i]小的,而不会对res的最大长度造成影响。而自所以要对res进行更改,是为了使得可能存在的比当前res值要小的序列的记录,以记录更长的LIS,比如:

nums = [5,6,1,2]

一开始,res = [5, 6],长度为2
而1的加入,有:res = [1,6]
2的加入,有:res = [1,2]
这时,长度也是2。

而假如nums = [5,6,1,2,3]
步骤一样,这时,res = [1,2,3] ,最大长度就是3了。

关于lower_bound( )和upper_bound( )的常见用法

3,代码实现

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if(nums.size() == 0)
            return 0;
        vector<int> res;
        for(auto &n : nums){
            auto itr = lower_bound(res.begin(), res.end(), n);
            if(itr == res.end())
                res.push_back(n);
            else
                *itr = n;
        }
        return res.size();
            
    }
};
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值