leetcode 870. 优势洗牌

108 阅读2分钟

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

1. 题目与解析

给定两个大小相等的数组 nums1 和 nums2,nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描述。

返回 nums1 的任意排列,使其相对于 nums2 的优势最大化。

输入:nums1 = [2,7,11,15], nums2 = [1,10,4,11]

输出:[2,11,7,15]

输入:nums1 = [12,24,8,32], nums2 = [13,25,32,11]

输出:[24,32,8,12]

根据题意,第一反应是通过贪心算法确定排列组合的方式:

  1. 升序将两个数组都排序;
  2. 利用双指针,由小到大的寻找比nums2中数值大的第一个数值,填写到对应的位置;
  3. 经过前两步,如果num1中的所有值都已经使用了,那么就已经找到了答案解,如果num1中有部分值没有使用,那就把这些值记录下来,之后随意顺序填写到答案解空白的位置即可。

2. 题解

  1. 针对num2的改造,根据我们前面的分析,我们需要在双指针比较大小的过程中完成一个对于num2 中元素原来位置的寻址过程,因此需要对nums2进行简单的改造:
int len = nums1.length;
int[][] nums2List = new int[len][2];
for (int i = 0; i < len; i++) {
    nums2List[i] = new int[]{nums2[i], i};
}
  1. 之后我们就可以针对nums1以及改造后的nums2List进行升序排序,这里可以借助Java中的Arrays.sort()来完成:
Arrays.sort(nums1);
Arrays.sort(nums2List, new Comparator<int[]>() {
    @Override
    public int compare(int[] o1, int[] o2) {
        return o1[0] - o2[0];
    }
});
  1. 由于nums1中元素有可能取值为0,为了区别出是否填入了元素,我们初始化答案解的原始数值为-1:
int[] ans = new int[len];
Arrays.fill(ans, -1);
  1. 之后就是对于排序后的列表进行双指针比较与答案解的初步填写:
Stack<Integer> sta = new Stack<>();

int index1 = 0, index2 = 0;
while (index1 < len && index2 < len) {
    if (nums2List[index2][0] >= nums1[index1]) {
        sta.push(nums1[index1]);
        index1++;
        continue;
    }
    ans[nums2List[index2][1]] = nums1[index1];
    index1++;
    index2++;
}
  1. 最后是将压入栈中的元素取出,填入答案解中还没有填写数值的位置:
for (int i = 0; i < len; i++) {
    if (ans[i] == -1) {
        ans[i] = sta.pop();
    }
}
return ans;

总体的解如下所示:

class Solution {
    public int[] advantageCount(int[] nums1, int[] nums2) {
        int len = nums1.length;
        int[][] nums2List = new int[len][2];
        for (int i = 0; i < len; i++) {
            nums2List[i] = new int[]{nums2[i], i};
        }
        Arrays.sort(nums1);
        Arrays.sort(nums2List, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[0] - o2[0];
            }
        });
        int[] ans = new int[len];
        Arrays.fill(ans, -1);
        Stack<Integer> sta = new Stack<>();

        int index1 = 0, index2 = 0;
        while (index1 < len && index2 < len) {
            if (nums2List[index2][0] >= nums1[index1]) {
                sta.push(nums1[index1]);
                index1++;
                continue;
            }
            ans[nums2List[index2][1]] = nums1[index1];
            index1++;
            index2++;
        }
        for (int i = 0; i < len; i++) {
            if (ans[i] == -1) {
                ans[i] = sta.pop();
            }
        }
        return ans;
    }
}