最长上升子序列LIS(Longest Increasing Subsequence)
注意dp的定义以及为什么要排序
300. 最长递增子序列
定义为考虑前 i 个元素,以第 i 个数字结尾的最长上升子序列的长度,注意 必须被选取。
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
n = len(nums)
dp = [1] * n
for i in range(n):
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[j]+1, dp[i])
return max(dp)
354. 俄罗斯套娃信封问题
同上,先按照第一维进行排序,然后在第二维寻找LIS
排序的意义:通过对第一维进行排序,在动态规划求的过程中,使得所有可能满足的前面的嵌套都已经求完,不存在后面的信封能放在前面的任何一个信封里面,例如[[5,4],[6,4],[6,7],[2,3]]
,最后一个信封能放在前面的信封里
class Solution:
def maxEnvelopes(self, envelopes: List[List[int]]) -> int:
envelopes.sort(key = lambda x: (x[0]))
n = len(envelopes)
dp = [1] * n
for i in range(n):
for j in range(i):
if envelopes[i][1] > envelopes[j][1] and envelopes[i][0] > envelopes[j][0] :
dp[i] = max(dp[j] + 1, dp[i])
return max(dp)
面试题 08.13. 堆箱子
和上面一模一样,复杂度也是
排序也只用排第一维,因为排序的意义在于遍历后面的箱子时确保前面的结果不会再改变了
class Solution:
def pileBox(self, box: List[List[int]]) -> int:
n = len(box)
res = 0
box.sort(key = lambda x:(x[0]))
dp = [box[i][2] for i in range(n)]
for i in range(n):
for j in range(i):
if box[i][0] > box[j][0] and box[i][1] > box[j][1] and box[i][2] > box[j][2]:
dp[i] = max(dp[j] + box[i][2], dp[i])
return max(dp)