持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情
每日一题 优势洗牌
原题链接:
示例 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
解题思路
这就是一题很典型的田忌赛马的题目 (看了好多解析都是这样说的,其实也没错啦)
我们照搬田忌赛马的核心思路:
- 用
nums1中的下等马 换nums2的上等马 - 用
nums1中的中等马 换nums2的下等马 - 用
nums1中的上等马 换nums2的中等马 获取nums1的上中下等马,很简单,我们仅需要对nums1进行一次排序就好,但是最终的结果需要是相对于nums2的优势最大化。 那么就表示我们不能直接对nums2进行排序操作,那么我们需要对nums2进行映射排序了。
不太懂?请看下面的详细解析
步骤一
- 对
nums1进行排序let newNums1 = nums1.sort((i, j) => i - j)
- 获取
nums2排序后的下标值映射let newNums2 = new Array(len).fill().map((value, key) => key).sort((i, j) => nums2[i] - nums2[j])
Q: 为什么需要 获取 nums2 的下标值映射,而不是直接对 nums2 进行排序
A:
- 最终的结果需要是相对于
nums2的优势最大化,是针对nums2的位置来进行排序的,所以我们需要保证nums2的顺序不发生改变 - 获取
nums2排序后的下标值映射是为了,可以通过下标映射来访问没有被排序后的nums2的值
// 排序 nums1 获得 从小到大的 数组
let newNums1 = nums1.sort((i, j) => i - j)
// nums2的键值对索引
// 获取后 对 索引进行排序 获得 nums2 从小到大的 排序键值索引
let newNums2 = new Array(len).fill().map((value, key) => key).sort((i, j) => nums2[i] - nums2[j])
步骤二
- 为已经上场比赛的选手占位置
// 然后我们需要获取左右两个节点
// 左右两个节点 是为了进行比对的时候 放置数据的位置用
let left = 0 // nums2的最小值
let right = len - 1 // nums2的最大值
- 设置最终要发挥的结果
// 最终结果
let res = new Array(len).fill(0)
步骤三
排序数组,判断 nums2 的最小值 和 nums1当前节点的最小值
if(newNums1[i] > nums2[newNums2[left]])如果nums1 的最小值 大于 nums2 的最小值,就安排题目进行比赛- 否则,就让他和 nums2 的最大值进行比赛
if(newNums1[i] > nums2[newNums2[left]]){
res[newNums2[left]] = newNums1[i]
++left
}else{
res[newNums2[right]] = newNums1[i]
--right
}
完整代码
var advantageCount = function (nums1, nums2) {
// 数组长度
let len = nums1.length
// 排序 nums1 获得 从小到大的 数组
let newNums1 = nums1.sort((i, j) => i - j)
// nums2的键值对索引
// 获取后 对 索引进行排序 获得 nums2 从小到大的 排序键值索引
let newNums2 = new Array(len).fill().map((value, key) => key).sort((i, j) => nums2[i] - nums2[j])
// 然后我们需要获取左右两个节点
// 左右两个节点 是为了进行比对的时候 放置数据的位置用
let left = 0 // nums2的最小值
let right = len - 1 // nums的最大值
// 最终结果
let res = new Array(len).fill(0)
// 遍历
for(let i = 0; i < len; ++i) {
// 如果 我们排序好的数组1的最小值 大于 nums2 的最小值
// 那么就让他们进行比赛 然后 最小值增加
// 如果小于 就用下等马 去 比上等马
if(newNums1[i] > nums2[newNums2[left]]){
res[newNums2[left]] = newNums1[i]
++left
}else{
res[newNums2[right]] = newNums1[i]
--right
}
}
return res
};