zoukankan      html  css  js  c++  java
  • leetcode:354 俄罗斯套娃信封问题(LIS)

     解题思路:

    根据题意,不难发现组合的元素,他们的长宽都是单调递增的,因此可以转化为最长上升子序列问题。

    首先按照长度从小到大对信封进行排序,长度相同,按照宽度从大到小进行排序。因为当长度相同,因为可能会把相同长的信封当做长度不同的信封给装起来了,如果宽度从大到小排序,就不会出现覆盖长度相同的情况。

    然后就是正常LIS方法,在coding的过程中,为了防止出现序列长度和信封长度相同的情况下出现保留了宽度较长的信封而没有保存宽度较短的信封,用了list存储结尾值,后来发现是没有必要的操作,因为不可能出现这种情况。。。

    def maxEnvelopes(envelopes):
        # dp[i]表示以第i个元素结尾的最长子序列长度
        dp= [0]*len(envelopes)+[0]
        # mx[j]表示长度为j的序列结尾值是多少,考虑到在信封的长度有可能重复,因此用list存储
        mx =[[0]] + [[100000] for i in range(len(envelopes))]
        # 按照长从小到大排,长度相同按照宽从大到小排
        a = sorted(envelopes,key = lambda x:(x[0],-x[1])) #
        length = len(a)
        a = [[0, 0]] + a +[[0,0]]
        #填充下标0,使元素从1开始算
        for i in range(1,length+1):
            #如果当前信封的长和上一个不同,说明已经处理完重复的信封了,后面的信封长度都比之前的长
            #因此,根据最优解的依赖关系,我们仅需保留mx[j]中结尾值最小的元素
            if a[i][0]!=a[i-1][0]:
                xx = mx.index([100000]) #优化查询,降低时间复杂度,使得整体复杂度由N*N降低到N*logN
                for j in range(xx,-1,-1):
                    mini = min(mx[j])
                    mx[j] = [mini]
            xx = mx.index([100000]) #优化查询,降低时间复杂度,使得整体复杂度由N*N降低到N*logN
            for j in range(xx,-1,-1):
                flag =False
                for k in mx[j]:
                    if a[i][1] > k: #只需要比mx[j]中某一个值大就可以构造成长度为j+1的子序列
                        dp[i] = j+1
                        mx[dp[i]].append(a[i][1])
                        flag = True
                        break
                if flag:
                    break
        #print(mx)
        return max(dp)
     1 简化版
     2 class Solution(object):
     3     def maxEnvelopes(self,envelopes):
     4        # dp[i]表示以第i个元素结尾的最长子序列长度
     5         dp= [0]*len(envelopes)+[0]
     6         # mx[j]表示长度为j的序列结尾值是多少,考虑到在信封的长度有可能重复,因此用list存储
     7         mx =[0] + [100000 for i in range(len(envelopes))]
     8         # 按照长从小到大排,长度相同按照宽从大到小排
     9         a = sorted(envelopes,key = lambda x:(x[0],-x[1])) #
    10         length = len(a)
    11         a = [[0, 0]] + a +[[0,0]]
    12         #填充下标0,使元素从1开始算
    13         for i in range(1,length+1):
    14             xx = mx.index(100000) #优化查询,降低时间复杂度,使得整体复杂度由N*N降低到N*logN
    15             for j in range(xx,-1,-1):
    16                 if a[i][1] > mx[j]:
    17                     dp[i] = j+1
    18                     mx[dp[i]]= min(mx[dp[i]],a[i][1])
    19                     break
    20         #print(mx)
    21         return max(dp)
  • 相关阅读:
    hdu 2604 Queuing(矩阵快速幂乘法)
    hdu 5591 ZYB's Game
    hdu 5590 ZYB's Biology
    CodeForces
    uva 193 Graph Coloring(图染色 dfs回溯)
    uva 10004 Bicoloring(dfs二分染色,和hdu 4751代码差不多)
    CSU
    hdu 5115 Dire Wolf(区间dp)
    腾讯装扮下拉选项卡特效(QQ空间)
    楼梯式定位导航系统
  • 原文地址:https://www.cnblogs.com/ISGuXing/p/14485957.html
Copyright © 2011-2022 走看看