day56 动态规划part13 代码随想录算法训练营 300. 最长递增子序列
题目:300. 最长递增子序列
我的感悟:
- 之前做过,都忘记了,这次好好记思路
理解难点:
- dp[i] 是由昨天的历史遍历后,得到今天的值
听课笔记:
我的代码:
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
# 难点是dp的推导公式,
# dp[i]是截止到nums[i]结尾的最长递增序列的个数
# dp[i] = if dp[i]> dp[j] max(dp[i],dp[j]+1) # j 取 0~i
# 初始值均为1
dp = [1] * len(nums)
for i in range(1,len(nums)):
for j in range(0,i):
if nums[i] > nums[j]:
dp[i] = max(dp[i],dp[j]+1)
return max(dp)
通过截图:
进一步优化的代码:
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if len(nums) <= 1:
return len(nums)
dp = [1] * len(nums)
result = 1
for i in range(1, len(nums)):
for j in range(0, i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1)
result = max(result, dp[i]) #取长的子序列
return result
贪心的写法:
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if len(nums) <= 1:
return len(nums)
tails = [nums[0]] # 存储递增子序列的尾部元素
for num in nums[1:]:
if num > tails[-1]:
tails.append(num) # 如果当前元素大于递增子序列的最后一个元素,直接加入到子序列末尾
else:
# 使用二分查找找到当前元素在递增子序列中的位置,并替换对应位置的元素
left, right = 0, len(tails) - 1
while left < right:
mid = (left + right) // 2
if tails[mid] < num:
left = mid + 1
else:
right = mid
tails[left] = num
return len(tails) # 返回递增子序列的长度
查找的写法:
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
stack = []
for num in nums:
idx = bisect_left(stack, num) # 引入 bisect 查找函数,找num在stack的哪个位置,如果相同就返回它的左边
if idx == len(stack): # 如果找的0就把num放到0的位置,保持stack一直为最小的递增子序列
stack.append(num) # 序列相等就加入到列表里
else:
stack[idx] = num # 不相等就替换、
return len(stack)
资料:
300.最长递增子序列
今天开始正式子序列系列,本题是比较简单的,感受感受一下子序列题目的思路。
视频讲解:https://www.bilibili.com/video/BV1ng411J7xP
https://programmercarl.com/0300.%E6%9C%80%E9%95%BF%E4%B8%8A%E5%8D%87%E5%AD%90%E5%BA%8F%E5%88%97.html