300. 最长上升子序列

98 篇文章 1 订阅
83 篇文章 1 订阅

在这里插入图片描述

思路一:动态规划

建立dp表,dp[i]表示含第i个数字的最长上升子序列的长度
求dp[i]时,向前遍历找出比i元素小的元素j,则动态方程为dp[i] = max(dp[i],dp[j] + 1)

class Solution(object):
    def lengthOfLIS(self, nums):
        size = len(nums)
        if size <= 1:
            return size
        dp = [1] * size
        for i in range(1, size):
            for j in range(i):
                if nums[i] > nums[j]:
                    # + 1 的位置不要加错了
                    dp[i] = max(dp[i], dp[j] + 1)
        # 最后要全部走一遍,看最大值
        return max(dp)

思路二:二分查找

利用一个cell数组,用于保存最长上升子序列
对原序列进行遍历,将每位元素二分插入cell中:

  • 如果cell中的元素都比它小,直接将它插到最后
  • 否则,利用二分查找,用它覆盖掉比他大的元素中最小的那个

总之,思想就是让 cell 中存储比较小的元素。这样,cell 未必是真实的最长上升子序列,但长度是对的。

class Solution(object):
    def lengthOfLIS(self, nums):
        size = len(nums)
        if size <= 1:
            return size

        cell = [nums[0]]
        for i in nums[1:]:
            #cell中元素都比它小
            if i > cell[-1]:
                cell.append(i)
                continue
            
            #否则,利用二分查找,进行覆盖
            l, r = 0, len(cell) - 1
            while l < r:
                m = l + (r - l) // 2
                if cell[m] < i:
                    l = m + 1
                else:
                    r = m
            cell[l] = i
        return len(cell)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值