题目:给定一个N行2列的二维数组,每一个小数组的两个值分别代表一个信封的长和宽。如果信封A 的长度都小于信封B,那么信封A可以放在信封B里,请返回信封最多嵌套多少层
举例:
matrix = [[3,4],[2,3],[4,5],[1,3],[2,2],[3,6],[1,2],[3,2],[2,4]]
信封最多可以套4层,从里到外分别是[1,2],[2,3],[3,4],[4,5],所以返回4
时间复杂度为O(NlogN)
思路:数组长度从小到达排序,长度相等的信封宽度按照从大到小排序
长度排序之后,可以忽略长度,只看宽度数组,问题转化为宽度数组的最长递增子序列问题
# encoding = 'utf-8'
import numpy as np
matrix = [[3,4],[2,3],[4,5],[1,3],[2,2],[3,6],[1,2],[3,2],[2,4]]
matrix.sort(key=lambda x: (x[0],-x[1]))
arr = []
for i in range(len(matrix)):
arr.append(matrix[i][1])
def getOrderLIS(arr,dp):
maxlen = 0
index = 0
"""找到最大值及索引"""
for i in range(len(arr)):
if arr[i] > maxlen:
maxlen = arr[i]
index = i
res = [0 for i in range(maxlen)]
res[maxlen-1]= arr[index]
maxlen -=1
"""找到之后,从右向左查找"""
for j in range(index,-1):
if arr[j] < arr[index] and dp[j] == dp[index] - 1:
res[maxlen-1] = arr[j]
maxlen -=1
index = j
return res
def getdp2(arr):
dp = [0 for i in range(len(arr))]
ends = [0 for i in range(len(arr))]
right = 0
dp[0] = 1
ends[0] = arr[0]
for i in range(1,len(arr)):
l = 0
r = right
while l <= r:
m = (l+r)//2
if arr[i] > ends[m]:
l = m + 1
else:
r = m - 1
right = max(right,l)
dp[i] = l + 1
ends[l] = arr[i]
return dp
def getlist(arr):
if arr == None or len(arr) == 0:
return None
dp = getdp2(arr)
return getOrderLIS(arr,dp)
getlist(arr)
最长递增子序列问题可参考:
https://blog.csdn.net/weixin_41362649/article/details/98470219