Leetcode 300. Longest Increasing Subsequence

这道题最优解法是利用dp + 二分,可以达到O(nlogn)的时间复杂度。

dp[i]存放长度为i+1的递增子序列最小的末尾数字。比如,nums = [4, 5, 6, 3],则所有的递增系列为:

len = 1 :[4], [5], [6], [3]  => dp[0] = 3

len = 2 : [4, 5], [5, 6]        => dp[1] = 5

len = 3 : [4, 5, 6]              => dp[2] = 6

显然dp数组是递增序列,因此,遍历nums数组时,需要做:

(1)如果nums[i]比dp中所有数字都大,则将nums[i]放入dp数组尾部

(2)如果存在dp[i-1] < nums[i] < dp[i],则更新dp[i] = nums[i]

最后输出dp数组的长度即可

import bisect
class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) <= 1:
            return len(nums)
        
        # dp[i] 表示长度为i的subsequence结尾最小为多少
        # dp[i]为递增数组
        dp = [nums[0]]
        for i in range(1, len(nums)):
            num = nums[i]
            if num > dp[-1]:
                dp.append(num)
            elif num < dp[-1]:
                # 找出比num大的第一个数字
                idx = bisect.bisect_right(dp, num)
                if idx == 0 or dp[idx-1] < num:
                    dp[idx] = num
        return len(dp)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值