夯实算法-优势洗牌

128 阅读2分钟

题目:优势洗牌

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

解题思路

核心思路是将两个数组都进行排序,然后每次用nums1中未被排列的最大值去和nums2中未被比较的最大值进行比较,赢了就放在相应位置上,输了就把nums1中未被排列的最小值放在相应位置上。

怎样知道nums1中未被排列的最大值和最小值?

因为数组nums1经过排序,对于有序数组,只需要使用双指针来记录未被排列的边界即可。 怎样知道相应位置的索引?

相应位置就是nums2中未被比较过的最大值对应的索引,所以不能直接对nums2中的元素进行排序,需要带着索引进行排序。另外,每次需要取出最大值,自然而然想到了大根堆。因此利用PriorityQueue的定制排序可以轻松实现。

对于num2中的每一个元素,在num1中找到一个比它大的元素即可。这样的话思路很清晰,直接对两个数组进行循环遍历,然后找到对应的值。

代码实现

public int[] advantageCount(int[] nums1, int[] nums2) {
    int n = nums1.length;
    //nums1 从小到大排序
    Arrays.sort(nums1);
    // nums2 从大到小排序(带上索引)
    PriorityQueue < int[] > n2Sorted = new PriorityQueue < > (
        (a, b) - > {
            return b[1] - a[1];
        }
    );
    for (int i = 0; i < nums2.length; i++) {
        n2Sorted.offer(new int[] {
            i, nums2[i]
        });
    }
    int[] res = new int[n];
    // 左右指针记录nums1中没被排列过的元素
    int left = 0;
    int right = n - 1;
    while (!n2Sorted.isEmpty()) {
        int[] n2 = n2Sorted.poll();
        if (nums1[right] > n2[1]) {
            res[n2[0]] = nums1[right--];
        } else {
            res[n2[0]] = nums1[left++];
        }
    }
    return res;
}

运行结果

Snipaste_2023-04-30_23-30-57.png

复杂度分析

  • 空间复杂度:O(n)
  • 时间复杂度:O(n)

掘金(JUEJIN) 一起分享知识, Keep Learning!