前言
这道题有下标数组的使用,建议先做:
解析:
题目描述
给定两个长度相等的数组 n u m s 1 nums1 nums1 和 n u m s 2 nums2 nums2, n u m s 1 nums1 nums1 相对于 n u m s 2 nums2 nums2 的优势可以用满足 n u m s 1 i > n u m s 2 i nums1i > nums2i nums1i>nums2i 的索引 i i i 的数目来描述
返回 n u m s 1 nums1 nums1 的任意排列,使其相对于 n u m s 2 nums2 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
解法
这是一个田忌赛马的问题,田忌赛马指的是,田忌有上、中、下等马,齐威王有上、中、下等马,齐威王的上等马比田忌的上等马好,其它的也是这样
当田忌以下面的方式对位时,就会失败:

当田忌以另一种方式对位时,就能获胜:

这里就衍生出了一种思想,先将两个人的马按照实力升序排序:

田忌的下等马无法赢过齐威王的所有马,所以让它去拖累齐威王的上等马
田忌的中等马最低能赢过齐威王的下等马,所以让它和齐威王的下等马比
田忌的上等马最低能赢过齐威王的中等马,所以让它和齐威王的中等马比
此时就会得到前一张图的结果
这道题目就用到了这种思想,先将两个数组 n u m s 1 nums1 nums1 和 n u m s 2 nums2 nums2 排升序,定义 l e f t left left 指向 n u m s 2 nums2 nums2 的开头, r i g h t right right 指向 n u m s 2 nums2 nums2 的末尾:

- n u m s i < = n u m s 2 l e f t numsi <= nums2left numsi<=nums2left 时,说明比不过,让它去拖累最大值, r e t r i g h t = n u m s i , r i g h t − − retright = numsi, right-- retright=numsi,right−−
- n u m s i > n u m s 2 l e f t numsi > nums2left numsi>nums2left 时,说明比得过,让它进行比较, r e t l e f t = n u m s i , l e f t + + retleft = numsi, left++ retleft=numsi,left++
最终得到结果:

看起来和题目要的答案不同,因为结果中的数据,对应的是排了升序的 n u m s 2 nums2 nums2 中的数据。如果想在不影响映射关系的情况下排序,可以创建一个下标数组,对下标数组进行排序
代码
cpp
class Solution {
public:
vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2)
{
vector<int> indices(nums1.size());
for (int i = 0;i < indices.size();++i)
{
indices[i] = i;
}
sort(indices.begin(), indices.end(), [&](int i, int j){
return nums2[i] < nums2[j];
});
sort(nums1.begin(), nums1.end());
vector<int> ret(nums1.size());
int left = 0, right = indices.size() - 1;
for (int i = 0;i < nums1.size();++i)
{
if (nums1[i] <= nums2[indices[left]])
{
ret[indices[right]] = nums1[i];
right--;
}
else
{
ret[indices[left]] = nums1[i];
left++;
}
}
return ret;
}
};