354. 俄罗斯套娃信封问题

https://leetcode-cn.com/problems/russian-doll-envelopes/

算法分析

首先我们从两种情况来讨论这个问题:

  • w无重复值(即信封的宽度每个信封都不一样)
  • w可以重复(即信封的宽度存在一样的,题目就是这种情况)

针对情况I

当每个信封的宽度和高度不一样时,我们可以对信封按照宽度从小到大进行排序,比如针对信封[[3,2],[2, 4],[4,3],[5, 6],[6,5]排序后变为
w: 2 -> 3 -> 4 -> 5 -> 6
h: 4 -> 2 -> 3 -> 6 -> 5

此时,因为信封的宽度w已经是从小到大排列了,要想信封可以套,这要求关于信封高度h的数组[4, 2, 3, 6, 5]是的子序列是递增的,且要求是最长的(题目要求的是最多的信封),所以可以转化为另一个问题:给定数组,求它的最长递增子序列(也称最长上升子序列)。关于这个问题在leetcode300有具体描述。

针对情况Ⅱ

对于情况Ⅱ,我们首先像情况I一样考虑,对信封的宽度w按从小到大排序,那么此时面临一个问题,对于相同宽度的信封的高h怎么进行排序,如果我们也按照从小到大排序,那么此时按照信封高求出来的最长递增子序列有可能存在宽度w相同的情况。
举个栗子:
当宽度w = 1时, 此时有3个信封,h = 2, 3, 4
当宽度w = 2时,此时有两个信封,h = 3, 6
按照上面的排序方式排序后,
w: 1 -> 1 -> 1 -> 2 -> 2
h: 2 -> 3 -> 4 -> 3 -> 6
此时数组h的最长递增子序列为[2, 3, 4, 6]显然不符合条件。所以这种排序方式是错误的。

那么正确的排序方式是什么样的呢,就是当w相同时,h逆序,从大到小排列,这样你可以想一下,针对h求出来的最长递增子序列不会存在w相等,而h递增的情况,因为w相同的时候,右边的数总是小于等于左边的数,不会出现在最长递增子序列里面。
还是上面那个栗子排序后:
w: 1 -> 1 -> 1 -> 2 -> 2
h: 4 -> 3 -> 2 -> 6 -> 3
此时数组h的最长递增子序列长度为2([4, 6]或[3, 6]或者其他),即最多有两个信封可以套。

 1 //二维数组排序
2 type pair struct{
3 x int
4 y int
5 }
6
7 type Type []pair
8
9 func (t Type) Len() int{
10 return len(t)
11 }
12
13 func (t Type) Less(i,j int) bool{
14 if t[i].x < t[j].x {
15 return true
16 }else if t[i].x > t[j].x{
17 return false
18 }else{
19 //相同x值,逆序
20 return t[i].y > t[j].y
21 }
22 }
23
24 func (t Type) Swap(i,j int) {
25 t[i],t[j] = t[j],t[i]
26 }
27
28
29 func maxEnvelopes(envelopes [][]int) int {
30 n := len(envelopes)
31 if n<= 1{
32 return n
33 }
34 var p Type
35 for i:=0;i<n;i++{
36 p = append(p,pair{envelopes[i][0],envelopes[i][1]})
37 }
38 sort.Sort(p)
39 var h []int
40 for i:=0;i<n;i++{
41 h = append(h,p[i].y)
42 }
43 //对h数组进行LIS
44 return LIS(h)
45 }
46 func MAX(i,j int) int{
47 if i<j{
48 return j
49 }else{
50 return i
51 }
52 }
53 //2 3 5 1 3 4
54 func LIS(h []int) int{
55 n := len(h)
56 dp := make([]int,n)
57 dp[0] = 1
58 res := 0
59 for i:=1;i<n;i++{
60 m := 0
61 for j:=0;j<i;j++{
62 if h[j] < h[i]{
63 m = MAX(m,dp[j])
64 }
65 dp[i] = m+1
66 }
67 res = MAX(dp[i],res)
68 }
69 return res
70 }

优化1、排序优化  2、LIS算法优化

排序直接对[][]int数组进行排序
type Env [][]int

func (e Env) Len() int{
return len(e)
} func (e Env) Less(i,j int) bool{
if e[i][0] == e[j][0]{
return e[i][1] > e[j][1]
}
return e[i][0] < e[j][0]
} func (e Env) Swap(i,j int) {
e[i],e[j] = e[j],e[i]
} func maxEnvelopes(envelopes [][]int) int {
n := len(envelopes)
if n<= 1{
return n
}
sort.Sort(Env(envelopes))
var h []int
for i:=0;i<n;i++{
h = append(h,envelopes[i][1])
}
//对h数组进行LIS
return LIS(h)
}
func MAX(i,j int) int{
if i<j{
return j
}else{
return i
}
}
//实际上逻辑是这样: 数组nums中的数nums[i]在 ends数组中二分查找第一个比他大的数并替换,若没有找到,则将nums[i]加在ends末尾,并且dp[i]=ends里面arr[i]的下标+1。
func LIS(nums []int) int{
n := len(nums)
if n<= 1{
return n
}
dp := make([]int,n)
//这里有个go 切片的隐藏bug。一开始ends := make([]int,n)了,这样的话,ends = append(ends,nums[i])是从第n+1个开始append
//这里非常容易出错,因为right = len(ends)-1这个大坑。
//这里可以变换下:right = max(left,right).
ends := make([]int,1)
dp[0] = 1
ends[0] = nums[0]
res := 0
for i:=1;i<n;i++{
left , right := 0,len(ends)-1
for left <= right{
m := left+(right-left)/2
if ends[m] < nums[i]{
left = m+1
}else{
right = m-1
}
}
if left < len(ends) && ends[left] >= nums[i]{
ends[left] = nums[i]
}else{
ends = append(ends,nums[i])
}
dp[i] = left+1
res = MAX(res,dp[i])
}
return res
}

  

1、线性DP 354. 俄罗斯套娃信封问题的更多相关文章

  1. Java实现 LeetCode 354 俄罗斯套娃信封问题

    354. 俄罗斯套娃信封问题 给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现.当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一 ...

  2. leetcode 354. 俄罗斯套娃信封问题(二维排序有关)

    题目描述 给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现.当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样. 请计算最多能有 ...

  3. Leetcode 354.俄罗斯套娃信封问题

    俄罗斯套娃信封问题 给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现.当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样. 请计 ...

  4. [Swift]LeetCode354. 俄罗斯套娃信封问题 | Russian Doll Envelopes

    You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envel ...

  5. LightOJ1044 Palindrome Partitioning(区间DP+线性DP)

    问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时 ...

  6. Codeforces 176B (线性DP+字符串)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...

  7. hdu1712 线性dp

    //Accepted 400 KB 109 ms //dp线性 //dp[i][j]=max(dp[i-1][k]+a[i][j-k]) //在前i门课上花j天得到的最大分数,等于max(在前i-1门 ...

  8. 动态规划——线性dp

    我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模 ...

  9. POJ 2479-Maximum sum(线性dp)

    Maximum sum Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33918   Accepted: 10504 Des ...

随机推荐

  1. MarkDown语法记录,还在用word,txt编写项目文档吗?

    开始之前 是不是在github上看项目的时候第一眼就要看项目介绍? 是不是经常在某些项目的代码里面看到一个README.MD文档 却不知道怎么写? 你是不是不知道,反正我是的. 作为一个程序员,可能写 ...

  2. oracle 查询当前数据库环境

    select SYS_CONTEXT('USERENV','AUTHENTICATION_TYPE')用户的认证类型 from dual;--用户的认证类型select SYS_CONTEXT('US ...

  3. Get提交方式中文乱码

    Get提交方式中文乱码 今天在servlet使用中,在Get方法中获取提交的中文参数,发现是乱码,我用的是Tomcat7. 在Tomcat9中: get方式的参数是放在请求头中,而Tomcat9对请求 ...

  4. 【C语言C++编程学习笔记】基础语法,第一个简单的实例编程入门教程!

    C语言/C++编程学习:一个简单的实例 让我们来看一个简单的C语言程序.从下面的程序可以看出编写C语言程序的一些基本特征.   如果你能知道该程序将会在显示器上显示一些内容,那说明你还是知道一些的! ...

  5. spring boot:shardingsphere+druid整合seata分布式事务(spring boot 2.3.3)

    一,shardingshpere为什么要整合seata? 分库分表是数据库扩展中最常用的处理方法, shardingshpere作为使用最广泛的分表中间件, 如果不支持分布式事务,则它的数据一致性就会 ...

  6. centos8平台使用blkid查看分区信息

    一,blkid的用途 blkid 命令是一个命令行工具,它可以显示关于可用块设备的信息 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/archite ...

  7. 【应用服务 App Service】NodeJS +Egg 发布到App Service时遇见 [ERR_SYSTEM_ERROR]: A system error occurred:uv_os_get_passwd returned ENOENT(no such file or directory)

    问题情形 本地NodeJS应用使用Egg脚手架构建,本地运行测试完全没有问题,发布后App Service后不能运行.通过登录到kudu后(https://<your web site>. ...

  8. Flutter Webview添加Cookie的正确姿势

    场景 h5页面要从cookie里面取数据,所以需要在flutter webview的cookie里面塞一些数据,设置的数据多达十几条:按照网上查的使用方式来设置,通过fiddler抓包发现,只能生效一 ...

  9. vue知识点10

    今天彻底掌握了如下: 1.解决回调地狱三种方案        callback async await Promise 2.中间件(middleware)        express.static  ...

  10. 《NASA对N+3代先进飞行器概念设计最终报告》阅读笔记

    民用航空的爆炸式增长已是未来的必然,灿烂的前景也意味着巨大的挑战,谁能发掘到未来技术的潜力,谁就能称霸下一个30年的天空! 文章目录 总概述 单双争霸 四点发现 方案分析 多维度分析 设计要求 品质因 ...