题目
给定一个无序的整数数组,找到其中最长上升子序列的长度。
链接: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)