持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情
给定两个大小相等的数组 nums1 和 nums2,nums1 相对于 nums2 的优势可以用满足 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 <= 10^5nums2.length == nums1.length0 <= nums1[i], nums2[i] <= 10^9
思路
看到这个题目,想到了田忌赛马的故事,我们可以采取同样的策略来获取nums1相对nums2的优势,我们需要在nums1中找到大于nums2[i]的最小数字,如果存在这样的数字nums1[j],我们把nums1[j]和nums1[i]交换。如果不存在我们查找最小值nums1[j]并交换。
解题
解法一
循环遍历nums2,从nums1中查找大于nums2[i]的最小数,如果没有找到,就用nums1中的最小值,此方法可以求解,但是提交的时候会超出时间限制,不符合要求。
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var advantageCount = function (nums1, nums2) {
for (let i = 0; i < nums2.length; i++) {
let num = nums2[i];
let n = i;
for (let j = i + 1; j < nums1.length; j++) {
if (
(nums1[n] > num && nums1[j] > num) ||
(nums1[n] <= num && nums1[j] <= num)
) {
n = nums1[n] > nums1[j] ? j : n;
} else {
n = nums1[n] > nums1[j] ? n : j;
}
}
if (n !== i) {
let temp = nums1[i];
nums1[i] = nums1[n];
nums1[n] = temp;
}
}
return nums1;
};
解法二
和解法一思路一致,只是从nums1中查找大于nums2[i]的最小数的时候做了一点优化,先把nums1排序,再二分查找。
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var advantageCount = function (nums1, nums2) {
const res = new Array(nums1.length);
nums1.sort((a, b) => a - b);
const find = (n) => {
let left = 0;
let right = nums1.length - 1;
while (left <= right) {
const mid = (left + right) >> 1;
if (nums1[mid] <= n) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
};
for (let i = 0; i < nums2.length; i++) {
let idx = find(nums2[i]);
idx = idx < nums1.length ? idx : 0;
res[i] = nums1.splice(idx, 1)[0];
}
return res;
};
解法三
解法二虽然可以满足要求,不会超时,但是时间效率很差,还要继续优化,可以改为贪婪算法,在解法二的基础上,把num2也进行排序,并用双指针求解,具体看代码
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var advantageCount = function (nums1, nums2) {
const n = nums1.length;
nums1.sort((a, b) => a - b);
const idx1 = new Array(n).fill(null).map((_, i) => i);
idx1.sort((a, b) => nums2[a] - nums2[b]);
const res = new Array(n);
let left = 0;
let right = n - 1;
for (let i = 0; i < n; i++) {
if (nums1[i] > nums2[idx1[left]]) {
res[idx1[left]] = nums1[i];
left++;
} else {
res[idx1[right]] = nums1[i];
right--;
}
}
return res;
};