"""
给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:
可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?
"""
# 方法一 动态规划
# 时间复杂度要求达到 o(nlogn)?? 意味着什么?。。意味着可能需采用二分查找
def lengthOfLIS1(nums):
n = len(nums)
dp = [1] * n
for i in range(1, n):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j]+1)
return max(dp or [0])
# 方法二 二分法
def lengthOfLIS2(nums):
tails, res = [0]*len(nums), 0
for num in nums:
i, j = 0, res
while i < j:
m = (i+j) //2
if tails[m] < m:
i = m+1
else:
j = m
tails[i] = num
if j == res:
res += 1
return res
def lengthOfLIS3(nums):
#时间复杂度为O(n * log(n))
# if not nums: return 0
tails = [float('-inf')] * len(nums)
res = 0
for num in nums:
if num > tails[res - 1]:
tails[res] = num
res += 1
continue
left, right = 0, res - 1
while left < right:
mid = (left + right) // 2
if num <= tails[mid]:
right = mid
else:
left = mid + 1
tails[right] = num
return res
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
# 堆数 piles = len(top)
top = [] # 堆顶元素数组
for poker in nums: # poker 当前牌
# find left bound
# 其实质是right往left方向靠
left = 0
right = len(top)
while left < right:
mid = (left + right) // 2
if top[mid] == poker:
right = mid
elif top[mid] < poker:
left = mid + 1
elif top[mid] > poker:
right = mid
# "left" is the left bound
if left == len(top):
top.append(poker)
else:
top[left] = poker
return len(top)
nums = [10, 9, 2, 5, 3, 7, 101, 18]
print(lengthOfLIS1(nums))
300_最长上升子序列
最新推荐文章于 2023-04-26 22:42:50 发布