题目描述
给定两个长度相等的数组 nums1 和 nums2,重新排列 nums1,使得尽可能多的位置满足 nums1[i] > nums2[i]。 返回重排之后的 nums1。
这道题经典别名:田忌赛马问题 。 策略核心:用我方刚好能赢对方的最小马去赢;赢不了的小马直接拿去消耗对方最强的马,保住我方强马赢其他对手。
思路详解
整体思路
- 对
nums1升序排序:我方马匹从小到大排好。 - 创建下标数组
index2,存储nums2的原始下标,不对 nums2 本身排序。 - 排序
index2:排序规则是nums2对应下标的值从小到大。 作用:我们可以拿到 nums2 从小到大的对手,但是还能记住对手原来在数组哪个位置,方便最后填写答案数组。 - 双指针:
left:指向 nums2 剩下最弱对手right:指向 nums2 剩下最强对手
- 逐个拿 nums1 最小的马决策:
- 能赢当前最弱对手:就派它上场赢下这场,left 右移。
- 赢不了:直接拿去送给对方最强的马,牺牲掉,right 左移。
cpp
class Solution {
public:
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
sort(nums1.begin(), nums1.end());
int n = nums1.size();
vector<int> index2(n);
for (int i = 0; i < n; i++) {
index2[i] = i;
}
sort(index2.begin(), index2.end(), [&](int i, int j) {
return nums2[i] < nums2[j];
});
vector<int> ret(n);
int left = 0, right = n - 1;
for (auto e : nums1) {
if (e > nums2[index2[left]])
ret[index2[left++]] = e;
else
ret[index2[right--]] = e;
}
return ret;
}
};