leetcode
leetcode 751 ~ 800
优势洗牌

优势洗牌

难度:

标签:

题目描述

代码结果

运行时间: 108 ms, 内存: 33.1 MB


/*
 * 思路:
 * 使用Java Stream的方式来实现优势洗牌。
 * 首先将nums1和nums2进行排序,并保留nums2的索引。
 * 然后使用双指针来分配nums1中的元素。
 */
import java.util.Arrays;
import java.util.stream.IntStream;

public class SolutionStream {
    public int[] advantageCount(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        int n = nums1.length;
        int[] result = new int[n];
        Integer[] indices = IntStream.range(0, n).boxed().toArray(Integer[]::new);
        Arrays.sort(indices, (a, b) -> Integer.compare(nums2[a], nums2[b]));

        int left = 0, right = n - 1;
        for (int num : nums1) {
            if (num > nums2[indices[left]]) {
                result[indices[left]] = num;
                left++;
            } else {
                result[indices[right]] = num;
                right--;
            }
        }
        return result;
    }
}

解释

方法:

这个题解采用了贪心算法的思想。首先,对nums1进行排序,以便尽可能将较小的值与nums2中较小的值匹配。同时,对nums2的索引进行排序,基于nums2的值进行排序,以便我们可以从nums2的最小值开始尝试匹配。接着,我们遍历排序后的nums1,尝试为每个nums2中的值找到一个大于它的最小nums1中的值。如果nums1中的当前值大于nums2中当前考虑的最小值,我们就把这个值分配给它,以此来最大化优势。如果不大于,则把这个值分配给当前nums2中的最大值的位置,尽可能减小'损失'。通过这种方式,我们可以保证nums1的优势最大化。

时间复杂度:

O(n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在实现算法时选择对 nums1 进行排序,而 nums2 只对索引进行排序而不是直接对数组排序?
在算法中,nums1 排序的目的是为了能够从小到大尝试为 nums2 的元素寻找优势值。如果直接对 nums2 排序,虽然可以按照从小到大处理 nums2 的元素,但这会改变 nums2 元素的原始位置,从而无法将优势值正确地放回原数组的对应位置。通过对 nums2 的索引进行排序,我们既保留了能够按值处理的顺序,又能通过索引将计算的结果放回到原始的数组结构中,这对解题是非常关键的。
🦆
在算法中,将不能优势的 nums1 值分配给当前 nums2 的最大值位置,这种策略是如何帮助减小损失的?
这种策略的核心思想是尽量利用 nums1 中的较小值去匹配 nums2 中的较大值,从而将这些较小值的影响最小化。如果 nums1 中的值无法给 nums2 中的当前最小值带来优势,那么这个 nums1 的值相对较小,将其匹配到 nums2 中的最大值上,可以避免浪费一个较大的 nums1 值在一个大的 nums2 值上,这样可以为后续的匹配留下更有优势的 nums1 值,从而在整体上减小了“损失”。
🦆
算法中提及使用双指针 L 和 R,这种双指针策略在这个特定问题中是如何工作的?能否详细解释双指针的移动规则和它们各自的作用?
双指针 L 和 R 在算法中分别指向 nums2 索引排序后的最小位置和最大位置。L 用于尝试寻找可以给 nums2 中当前最小值带来优势的 nums1 值,如果当前遍历到的 nums1 值大于 nums2[i2[L]](nums2 索引排序后的当前最小值),则将这个 nums1 值分配给它,并将 L 指针向右移动,即向更大的值移动。如果当前 nums1 值不能优势当前考虑的 nums2 的最小值,那么用 R 指针指向的位置,即 nums2 中的最大值位置分配这个 nums1 值,然后将 R 指针向左移动,即向更小的值移动。这样的策略不仅使得能够优势的情况下尽可能利用,而且在不能优势的情况下尽可能减小损失。

相关问题