Leetcode-300. Longest Increasing Subsequence 最长上升子序列 (经典DP) -python

题目

给定一个无序的整数数组,找到其中最长上升子序列的长度。
链接:https://leetcode.com/problems/longest-increasing-subsequence/

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.

思路及代码

DP
  • dp[i]:包含第i位在内的子序列中,最长的长度
  • dp[i] = max(dp[j]) + 1
    • 其中nums[j] < nums[i]
    • 如果没有比第i位小的数,dp[i] = 1
  • 初始值dp[0] = 1
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        dp = [1] * len(nums)
        for i in range(len(nums)):
            prev = 0
            for j in range(i-1, -1, -1):
                if nums[i] > nums[j] and dp[j] > prev:
                    prev = dp[j]
            dp[i] = prev + 1
        return max(dp)
耐心排序 patience sorting
  • 耐心排序
  • 记录每一个长度的子序列最后一位数的最小值
    • 比如找长度为1的[1],[2],[4],则记录1
    • 找长度为2的子序列[1,2],[1,4],[2,4],则记录2
    • 即tail的值为[1,2,4]
  • 不仅可以返回长度,还可以返回最长子序列本身
def lengthOfLIS(self, nums):
	# tails[i]: 长度为i+1的子序列,末尾最小值(持续遍历nums的过程中持续更新)
    tails = [0] * len(nums)
    size = 0 # 记录最长长度
    for x in nums:
        i, j = 0, size
        while i != j:
            m = (i + j) / 2
            # 目前记录的长度为m的子序列最后一位 < 当前遍历到的数字
            if tails[m] < x: 
            	# 则当前位数字小,不用动,继续往后看
                i = m + 1
            # 效果是往后能把i(当前遍历到的size)往后挪一位
            else:
                j = m
        tails[i] = x
        size = max(i + 1, size) # 长度为i+1
    return size

复杂度

T = O ( n 2 ) O(n^2) O(n2) -> O ( n l o g n ) O(nlogn) O(nlogn)
S = O ( n ) O(n) O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值