LeetCode 0870. 优势洗牌 - LetMeFly趣解田忌赛马:能赢则赢,否则摆烂(贪心)
Posted Tisfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 0870. 优势洗牌 - LetMeFly趣解田忌赛马:能赢则赢,否则摆烂(贪心)相关的知识,希望对你有一定的参考价值。
【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 ) O(n\\log n) O(nlogn),其中 n n n是马匹个数。排序的时间复杂度是 O ( n log n ) O(n\\log n) O(nlogn),选马的时间复杂度是 O ( n ) O(n) O(n)
- 空间复杂度 O ( n ) O(n) O(n)。我们使用了额外的空间来记录对手马匹的“出场编号”信息( O ( n ) O(n) O(n)),且使用了额外空间记录了自己“指针扫过但因战力不足而未出场的🐎”( O ( n ) O(n) O(n));排序的空间复杂度是 O ( log n ) O(\\log n) O(logn)
AC代码
C++
typedef pair<int, int> pii; // <战力, 出场编号>
class Solution
public:
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2)
int n = nums1.size();
// 记录对手(nums2)出场顺序信息
vector<pii> tempNums2(n);
for (int i = 0; i < n; i++)
tempNums2[i] = nums2[i], i;
// 对对手、自己马匹排序
sort(tempNums2.begin(), tempNums2.end());
sort(nums1.begin(), nums1.end());
vector<int> ans(n); // ans存放最终答案
int loc1 = 0; // 自己的马匹的“指针”
vector<int> unused; // 指针扫过但未出场的马,留着摆烂使用
for (int i = 0; i < n; i++) // 遍历对手马
while (loc1 < n && nums1[loc1] <= tempNums2[i].first) // 自己的马战力不足
unused.push_back(nums1[loc1]); // 放入“未使用数组”
loc1++; // 指针后移
if (loc1 == n) // 指针到数组尾部,扫描完毕,无高战力马可出场,开始摆烂,摆烂完退出循环
int locUnused = 0; // 为了遍历“未使用数组”
while (i < n) // 为后面所有的“对手无敌马”分配自己的“摆烂马”
ans[tempNums2[i++].second] = unused[locUnused++];
break; // 摆烂完退出循环
ans[tempNums2[i].second] = nums1[loc1++]; // 为对手的彼马分配自己的 未使用且战力更强 的战力尽可能小马
return ans;
;
同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/127207642
以上是关于LeetCode 0870. 优势洗牌 - LetMeFly趣解田忌赛马:能赢则赢,否则摆烂(贪心)的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 870 优势洗牌[自定义排序] HERODING的LeetCode之路
LeetCode 870 优势洗牌[自定义排序] HERODING的LeetCode之路
LeetCode 870. 优势洗牌(根据数值对索引排序)/ 856. 括号的分数(栈) / 801. 使序列递增的最小交换次数(动态规划)
LeetCode 870. 优势洗牌(根据数值对索引排序)/ 856. 括号的分数(栈) / 801. 使序列递增的最小交换次数(动态规划)