这道题最优解法是利用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)