美文网首页
leetcode-300 最长上升子序列 O(NlogN)解法

leetcode-300 最长上升子序列 O(NlogN)解法

作者: 全方位小白 | 来源:发表于2019-08-04 17:18 被阅读0次

1. 题目内容

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

示例:

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

说明:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 基本思路

来自极客时间的课程,覃超老师讲的,现在做笔记记录如下:

  1. 创建一个数组l用于记录当前的满足要求的最长的子序列;
  2. 遍历整个数组,并调整数组l
  3. 调整规则如下:
    <1> 若当前元素大于数组l中所有元素,则l长度加一,将当前元素添加入l
    <2> 否则,找到l中比当前元素大的元素中的最小值,用当前元素替换,使用二分查找(这也是时间复杂度中logN的来源);
    <3> 遍历完毕后返回l的长度即可

3. 代码实现(Python)

class Solution(object):
    def binary_search(self, num, lts):      # 二分查找,找到当前元素的插入位置
        l = len(lts)
        left = 0
        right = l - 1
        while left < right:
            mid = (left + right) // 2
            if lts[mid] < num < lts[mid+1]:
                return mid+1
            elif num > lts[mid]:
                left = mid+1
            else:
                right = mid

    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        lts = [nums[0]]
        for num in nums[1:]:
            if num > lts[-1]:
                lts.append(num)
            elif num < lts[0]:
                lts[0] = num
            elif num in lts:
                continue
            elif num < lts[-1]:
                n_l = self.binary_search(num, lts)
                lts[n_l] = num
        print(lts)
        return len(lts)


def main():
    nums = [10, 9, 2, 5, 3, 7, 101, 18, 20]
    a = Solution()
    res = a.lengthOfLIS(nums)
    print(res)


if __name__ == '__main__':
    main()

对于main()中给出的数组,遍历时子序列数组内容依次为:

[10]
[9]
[2]
[2, 5]
[2, 3]
[2, 3, 7]
[2, 3, 7, 101]
[2, 3, 7, 18]
[2, 3, 7, 18, 20]

4. 小结

本题较为常规的解法似乎是动态规划,时间复杂度为O(N^2),本文的解法似乎属于奇技淫巧型,但细想之下会觉得这是需要基础非常牢靠才能想得出的解法,因此记录一下。
此外,这一次顺便复习了二分查找的写法,发现之前掌握的很不牢靠,自己写的很痛苦,想用递归实现,后来去搜了一个例子,才学会,而且更新 left 或 right 的时候需要实际写一下看看要不要 mid±1.

相关文章

  • leetcode-300 最长上升子序列 O(NlogN)解法

    1. 题目内容 给定一个无序的整数数组,找到其中最长上升子序列的长度。 示例: 输入: [10,9,2,5,3,7...

  • BZOJ1669: [Usaco2006 Oct]Hungry

    题意给定长度为n的序列,求最长上升子序列复杂度O(nlogn)题解网上有很多关于最长上升子序列nlogn的求法,我...

  • 最长上升子序列(LIS)O(nlogn)优化

    LIS问题:求数组A[i]的最长(严格)上升子序列的元素个数。 先看一看O(n2)的动态规划算法,定义d[i]为以...

  • 12_6最长上升子序列LIS

    这是一个经典的LIS(即最长上升子序列)问题,请设计一个尽量优的解法求出序列的最长上升子序列的长度。 给定一个序列...

  • 公共子序列问题

    最长公共子序列 最长上升子序列 最长公共上升子序列

  • LintCode 最长上升子序列

    给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度。 说明 最长上升子序列的定义: 最长上升子序列问...

  • LintCode 最长上升子序列

    题目 给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度。 说明最长上升子序列的定义:最长上升子序列...

  • 最长上升子序列

    最长上升子序列(Longest Increasing Subsequence) 最长上升子序列方案数

  • LintCode 最长上升子序列

    题目 给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度。说明最长上升子序列的定义:最长上升子序列问...

  • 76. 最长上升子序列

    描述 给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度。 说明 最长上升子序列的定义: 最长上升子...

网友评论

      本文标题:leetcode-300 最长上升子序列 O(NlogN)解法

      本文链接:https://www.haomeiwen.com/subject/fjsydctx.html