[JavaScript / leetcode] 870. 优势洗牌

152 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情

每日刷题 2022.10.29

题目

  • 给定两个大小相等的数组 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^5
  • nums2.length == nums1.length
  • 0 <= nums1[i], nums2[i] <= 10^9

解题思路

  • nums2数组作为基准,来排序nums2数组,使用二分找到nums1中第一个大于当前的nums2的值,将其放到对应的位置上即可。
  • 这个题最主要的思考点是:B升序排序后,遍历B,在A中寻找大于B单个数字的最小值
  • 因此具体步骤如下:
    • AB先进行升序排序;
    • 遍历B,然后从A中寻找大于每个B数值的最小数值,无用数值用数组存储备用。这里对A的遍历位置做记忆处理;
    • 获取到可用值和无用值后,再对B副本进行遍历(顺序要和排序前的B保持一致),有可用值就用,无可用值就用无用值做备胎.

AC代码

var advantageCount = function(nums1, nums2) {
  nums1.sort((a, b) => a - b);
  let n = nums2.length, ans = [], map = new Map(), set = new Set();
  for(let i = 0; i < n; i++) {
    let idx = binary(nums2[i]);
    if(idx === -1) ans.push(-1);
    else {
      ans.push(nums1[idx]);
      map.set(idx, 1)
      set.add(idx);
    }
  }
  let use = [];
  // 还需要处理,当不存在的时候,需要将没有用过的填充进去
  for(let i = 0; i < n; i++) {
    if(!set.has(i)) use.push(i);
  }
  for(let i = 0, tar = 0; i < n; i++) {
    if(ans[i] === -1) {
      ans[i] = nums1[use[tar++]];
    }
  }
  return ans;
  function binary(cur) {
    let l = -1, r = n;
    while(l + 1 != r) {
      let mid = (l + r) >>> 1;
      if(nums1[mid] <= cur) {
        l = mid;
      }else {
        r = mid;
      }
    }
    if(map.has(r)) {
      // 当前的已经被使用过
      while(r < n) {
        r++;
        if(!map.has(r)) break;
      }
    }
    if(r === n) return -1;
    return r;
  }
};