300、最长递增子序列
第一种方法
基本思想:
动态规划
具体实现:
1、确定状态
(1)最后一步---以nums[i]这个数结尾的最长递增子序列的长度,设为dp[i]
(2)化为子问题---比nums[i]小的之前的nums为结尾的最长递增子序列的长度
2、转移方程
dp[i] = max(dp[i], dp[j] + 1)
3、初始条件和边界条件
dp初始化都为1
4、计算顺序
从前往后
代码:
# Dynamic programming. class Solution: def lengthOfLIS(self, nums: List[int]) -> int: if not nums: return 0 dp = [1] * len(nums) for i in range(len(nums)): for j in range(i): if nums[j] < nums[i]: # 如果要求非严格递增,将此行 '<' 改为 '<=' 即可。 dp[i] = max(dp[i], dp[j] + 1) return max(dp)
第二种方法:
基本思想:
二分搜索
具体实现:
书101页
while处是left<right
说明是开区间,right的值在top中刚开始总是top的长度
代码:
class Solution: def lengthOfLIS(self, nums: List[int]) -> int: top = [0]*len(nums) piles = 0 for i in range(len(nums)): poker = nums[i] left = 0 right = piles while left<right: mid = (left+right)//2 if top[mid]>poker: right = mid elif top[mid]<poker: left = mid + 1 else: right = mid if left == piles: piles += 1 top[left] = poker return piles
354、信封嵌套问题
基本思想:
动态规划
具体实现:
先对宽度w进行升序排序,如果遇到w相同的情况,则按照高度降序排序。
之后把h作为一个数组,在这个数组上计算出的最长递增子序列就是答案。
envelopes = [[1,8],[2,3],[5,4],[5,2]]
envelopes[1] = [2,3]
envelopes[1][1] =[3]
envelopes[j][1] =每个数组的第二个数
代码:
class Solution: def maxEnvelopes(self, envelopes: List[List[int]]) -> int: if not envelopes: return 0 n = len(envelopes) envelopes.sort(key=lambda x: (x[0], -x[1])) # x[0]代表按第一个维度行来升序排序,再-x[1]代表在行排序的基础上对列降序排序 f = [1] * n for i in range(n): for j in range(i): if envelopes[j][1] < envelopes[i][1]: f[i] = max(f[i], f[j] + 1) return max(f)
第二种方法:
class Solution: def maxEnvelopes(self, envelopes: List[List[int]]) -> int: if not envelopes: return 0 top = [1]*len(envelopes) envelopes.sort(key = lambda x:(x[0],-x[1])) piles = 0 for i in range(len(envelopes)): left, right = 0, piles poker = envelopes[i][1] while left < right: mid = (left + right)//2 if top[mid] > poker: right = mid elif top[mid] < poker: left = mid+1 else: right = mid if left == piles: piles += 1 top[left] = poker return piles