870.优势洗牌
【LetMeFly】趣解田忌赛马:能赢则赢,否则摆烂(贪心) - 870.优势洗牌
力扣题目链接:https://leetcode.cn/problems/advantage-shuffle/
给定两个大小相等的数组 nums1
和 nums2
,nums1
相对于 nums
的优势可以用满足 nums1[i] > nums2[i]
的索引 i
的数目来描述。
返回 nums1 的任意排列,使其相对于 nums2
的优势最大化。
示例 1:
输入:nums1 = [2,7,11,15], nums2 = [1,10,4,11] 输出:[2,11,7,15]
示例 2:
输入:nums1 = [12,24,8,32], nums2 = [13,25,32,11] 输出:[24,32,8,12]
提示:
1 <= nums1.length <= 105
nums2.length == nums1.length
0 <= nums1[i], nums2[i] <= 109
方法一:田忌赛马(贪心)
思路很简单,就是:
从对手战力最弱的🐎开始,每次从 自己未出场 且 战力大于对手的这匹🐎 的🐎中,挑选战力最小的一匹。
若无🐎可敌,则开始摆烂
举个例子,假如自己的五匹马的战力为12、24、8、32、6
,对手的五匹马的战力为13、25、32、11、998
从对手的战力最弱的🐎开始,先看对手战力为11
的🐎,再看战力为13
的🐎,再看25
,再看32
,最后看998
- 对于对手的
11
,自己的🐎中,未出场 且 战力大于11
的有12、24、32
,其中战力最小的是12
,因此选派自己的12
对抗对手的11
- 对于对手的
13
,自己的🐎中,未出场 且 战力大于13
的有24、32
,其中战力最小的是24
,因此选派自己的24
对抗对手的13
- 对于对手的
25
,自己的🐎中,未出场 且 战力大于25
的有32
,其中战力最小的是32
,因此选派自己的32
对抗对手的25
- 对于对手的
32
,自己的🐎中,没有 未出场 且 战力大于32
的🐎,无🐎可敌,开始摆烂!
怎么摆烂呢?反正也赢不了了,那么就在自己未出场的🐎中随便上吧!上谁都无所谓,反正也赢不了。
对面还有两匹马32、998
没有对手,自己还有两匹马8、6
没有出场。那就用自己的8
对抗对手的32
,自己的6
对抗对手的998
好了。
因此,对于对手的出场顺序(数组2)[13, 25, 32, 11, 998]
,我们的回敬(打乱的数组1)是:[24, 32, 8, 12, 6]
能胜三场,还行还行。
那么编程怎么实现呢?
其实不难发现,我们在挑选对手和自己的🐎时,在背后默默进行了排序操作。
我们将对手的[13, 25, 32, 11, 998]
默默排序成了[11, 13, 25, 32, 998]
作为出场顺序;我们将自己的[12, 24, 8, 32, 6]
默默排序成了[6, 8, 12, 24, 32]
以方便选取“大于敌方且尽可能小”的🐎。
但是需要注意的是,对手的马匹排序后,原始顺序不能丢失,因为我们默默地将对手马匹按战力排序了,对手可不会因为你的排序而改变自己的出场顺序。
因此,在对对手的马匹进行排序前,不如先做个手脚:将对手的<马匹战力, 出场编号>进行绑定,依据战力排序,排序后出厂编号信息不会丢失。
至于自己的🐎,用一个“指针”记录当前判断到了哪一匹,如果这一匹马的战力不大于当前遍历到的对手的🐎的战力,就指针后移,找到第一个大于对手战力的位置,就是自己“未出场 且 战力大于对手”的🐎中,战力最小的那匹。 (若自己这匹马战力不足,那么指针后移之前,记得将这匹马标记或者存起来,表示“指针扫过了但是未出场”,以到最后和敌方的“无敌之🐎”进行摆烂)
- 时间复杂度$O(n\log n)$,其中$n$是马匹个数。排序的时间复杂度是$O(n\log n)$,选马的时间复杂度是$O(n)$
- 空间复杂度$O(n)$。我们使用了额外的空间来记录对手马匹的“出场编号”信息($O(n)$),且使用了额外空间记录了自己“指针扫过但因战力不足而未出场的🐎”($O(n)$);排序的空间复杂度是$O(\log n)$
AC代码
C++
1 |
|
同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/127207642