贪心题目:优势洗牌

文章目录

题目

标题和出处

标题:优势洗牌

出处:870. 优势洗牌

难度

4 级

题目描述

要求

给定两个长度相等的数组 nums1 \texttt{nums1} nums1 和 nums2 \texttt{nums2} nums2。数组 nums1 \texttt{nums1} nums1 相对于数组 nums2 \texttt{nums2} nums2 的优势 为满足 nums1i > nums2i \texttt{nums1i} > \texttt{nums2i} nums1i>nums2i 的下标 i \texttt{i} i 的数目。

返回使 nums1 \texttt{nums1} nums1 相对于 nums2 \texttt{nums2} nums2 的优势最大化的 nums1 \texttt{nums1} nums1 的任意排列。

示例

示例 1:

输入: nums1 = 2,7,11,15, nums2 = 1,10,4,11 \texttt{nums1 = 2,7,11,15, nums2 = 1,10,4,11} nums1 = 2,7,11,15, nums2 = 1,10,4,11

输出: 2,11,7,15 \texttt{2,11,7,15} 2,11,7,15

示例 2:

输入: nums1 = 12,24,8,32, nums2 = 13,25,32,11 \texttt{nums1 = 12,24,8,32, nums2 = 13,25,32,11} nums1 = 12,24,8,32, nums2 = 13,25,32,11

输出: 24,32,8,12 \texttt{24,32,8,12} 24,32,8,12

数据范围

  • 1 ≤ nums1.length ≤ 10 5 \texttt{1} \le \texttt{nums1.length} \le \texttt{10}^\texttt{5} 1≤nums1.length≤105
  • nums2.length = nums1.length \texttt{nums2.length} = \texttt{nums1.length} nums2.length=nums1.length
  • 0 ≤ nums1i, nums2i ≤ 10 9 \texttt{0} \le \texttt{nums1i, nums2i} \le \texttt{10}^\texttt{9} 0≤nums1i, nums2i≤109

前言

这道题的情形和田忌赛马很相似。田忌赛马出自《史记·孙子吴起列传》,原文如下。

孙武既死,后百余岁有孙膑。膑生阿、鄄之间,膑亦孙武之后世子孙也。孙膑尝与庞涓俱学兵法。庞涓既事魏,得为惠王将军,而自以为能不及孙膑,乃阴使召孙膑。膑至,庞涓恐其贤于己,疾之,则以法刑断其两足而黥之,欲隐勿见。

齐使者如梁,孙膑以刑徒阴见,说齐使。齐使以为奇,窃载与之齐。齐将田忌善而客待之。忌数与齐诸公子驰逐重射。孙子见其马足不甚相远,马有上、中、下辈。于是孙子谓田忌曰:"君弟重射,臣能令君胜。"田忌信然之,与王及诸公子逐射千金。及临质,孙子曰:"今以君之下驷与彼上驷,取君上驷与彼中驷,取君中驷与彼下驷。"既驰三辈毕,而田忌一不胜而再胜,卒得王千金。于是忌进孙子于威王。威王问兵法,遂以为师。

解法

思路和算法

定义「优势元素」如下:将 nums 1 \textit{nums}_1 nums1 排列之后,如果两个数组的下标 i i i 处的元素满足 nums 1 i > nums 2 i \textit{nums}_1i > \textit{nums}_2i nums1i>nums2i,则将 nums 1 i \textit{nums}_1i nums1i 称为 nums 2 i \textit{nums}_2i nums2i 的优势元素。

为了使 nums 1 \textit{nums}_1 nums1 相对于 nums 2 \textit{nums}_2 nums2 的优势最大,根据贪心思想,应按照 nums 2 \textit{nums}_2 nums2 的元素递增的顺序依次寻找 nums 2 \textit{nums}_2 nums2 中的每个元素在 nums 1 \textit{nums}_1 nums1 中的优势元素,对于 nums 2 \textit{nums}_2 nums2 的每个元素 x x x,选择 nums 1 \textit{nums}_1 nums1 的剩余元素中大于 x x x 的最小元素作为 x x x 的优势元素,理由如下。

将数组 nums 2 \textit{nums}_2 nums2 按升序排序之后,假设存在两个相邻元素 x 1 x_1 x1 和 x 2 x_2 x2,其中 x 1 ≤ x 2 x_1 \le x_2 x1≤x2, nums 1 \textit{nums}_1 nums1 的剩余元素中大于这两个元素的最小元素分别是 y 1 y_1 y1 和 y 2 y_2 y2,则必有 y 1 ≤ y 2 y_1 \le y_2 y1≤y2。当 nums 1 \textit{nums}_1 nums1 相对于 nums 2 \textit{nums}_2 nums2 的优势最大时,应将 y 1 y_1 y1 作为 x 1 x_1 x1 的优势元素,将 y 2 y_2 y2 作为 x 2 x_2 x2 的优势元素。假设 x 1 x_1 x1 的优势元素是 y 3 y_3 y3 且 y 3 > y 1 y_3 > y_1 y3>y1,考虑以下两种情况。

  • 当 y 3 < y 2 y_3 < y_2 y3<y2 时,仍可以将 y 2 y_2 y2 作为 x 2 x_2 x2 的优势元素, nums 2 \textit{nums}_2 nums2 的其余更大元素的优势元素不变, nums 1 \textit{nums}_1 nums1 相对于 nums 2 \textit{nums}_2 nums2 的优势不变。

  • 当 y 3 ≥ y 2 y_3 \ge y_2 y3≥y2 时,在 nums 2 \textit{nums}_2 nums2 的其余更大元素中, nums 1 \textit{nums}_1 nums1 相对于 nums 2 \textit{nums}_2 nums2 的优势不变或减 1 1 1,不可能有更大的优势。

因此,对于 nums 2 \textit{nums}_2 nums2 中的每个元素 x x x,选择 nums 1 \textit{nums}_1 nums1 的剩余元素中大于 x x x 的最小元素作为 x x x 的优势元素,该贪心策略可以使 nums 1 \textit{nums}_1 nums1 相对于 nums 2 \textit{nums}_2 nums2 的优势最大。

由于这道题需要得到使 nums 1 \textit{nums}_1 nums1 相对于 nums 2 \textit{nums}_2 nums2 的优势最大化的 nums 1 \textit{nums}_1 nums1 的任意排列,因此需要记录使优势最大化的 nums 1 \textit{nums}_1 nums1 和 nums 2 \textit{nums}_2 nums2 之间的元素对应关系,并记录 nums 2 \textit{nums}_2 nums2 的每个元素所在下标。

具体做法是,创建二维数组 numsIndices 2 \textit{numsIndices}_2 numsIndices2 记录 nums 2 \textit{nums}_2 nums2 每个元素及下标,其中 numsIndices 2 i 0 = nums 2 i \textit{numsIndices}_2i0 = \textit{nums}_2i numsIndices2i0=nums2i, numsIndices 2 i 1 = i \textit{numsIndices}_2i1 = i numsIndices2i1=i,将 nums 1 \textit{nums}_1 nums1 按升序排序、将 numsIndices 2 \textit{numsIndices}_2 numsIndices2 按元素值升序排序,然后从左到右遍历 nums 1 \textit{nums}_1 nums1,遍历过程中维护 numsIndices 2 \textit{numsIndices}_2 numsIndices2 的下标 j j j 和 k k k,初始时 j j j 和 k k k 分别位于 numsIndices 2 \textit{numsIndices}_2 numsIndices2 的左端和右端,对于每个 nums 1 i \textit{nums}_1i nums1i,执行如下操作。

  • 如果 nums 1 i > numsIndices 2 j 0 \textit{nums}_1i > \textit{numsIndices}_2j0 nums1i>numsIndices2j0,则将 nums 1 i \textit{nums}_1i nums1i 作为 numsIndices 2 j 0 \textit{numsIndices}_2j0 numsIndices2j0 的优势元素,将 nums 1 i \textit{nums}_1i nums1i 填到结果排列的下标 numsIndices 2 j 1 \textit{numsIndices}_2j1 numsIndices2j1 处,然后将 j j j 向右移动一位。

  • 如果 nums 1 i ≤ numsIndices 2 j 0 \textit{nums}_1i \le \textit{numsIndices}_2j0 nums1i≤numsIndices2j0,则 nums 1 i \textit{nums}_1i nums1i 不能作为 numsIndices 2 \textit{numsIndices}_2 numsIndices2 中的任意剩余元素的优势元素,将 nums 1 i \textit{nums}_1i nums1i 填到结果排列的下标 numsIndices 2 k 1 \textit{numsIndices}_2k1 numsIndices2k1 处,然后将 k k k 向左移动一位。

上述遍历过程中, numsIndices 2 j 0 \textit{numsIndices}_2j0 numsIndices2j0 和 numsIndices 2 k 0 \textit{numsIndices}_2k0 numsIndices2k0 分别是 numsIndices 2 \textit{numsIndices}_2 numsIndices2 的剩余元素中的最小元素与最大元素,因此符合贪心策略。

遍历结束之后,结果排列即为使 nums 1 \textit{nums}_1 nums1 相对于 nums 2 \textit{nums}_2 nums2 的优势最大的一种排列。

代码

java 复制代码
class Solution {
    public int[] advantageCount(int[] nums1, int[] nums2) {
        int length = nums1.length;
        int[][] numsIndices2 = new int[length][2];
        for (int i = 0; i < length; i++) {
            numsIndices2[i][0] = nums2[i];
            numsIndices2[i][1] = i;
        }
        Arrays.sort(nums1);
        Arrays.sort(numsIndices2, (a, b) -> a[0] - b[0]);
        int[] permutation = new int[length];
        int index1 = 0, index2Left = 0, index2Right = length - 1;
        while (index1 < length && index2Left < length) {
            if (nums1[index1] > numsIndices2[index2Left][0]) {
                int currIndex = numsIndices2[index2Left][1];
                permutation[currIndex] = nums1[index1];
                index2Left++;
            } else {
                int currIndex = numsIndices2[index2Right][1];
                permutation[currIndex] = nums1[index1];
                index2Right--;
            }
            index1++;
        }
        return permutation;
    }
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组 nums 1 \textit{nums}_1 nums1 和 nums 2 \textit{nums}_2 nums2 的长度。创建包含 nums 2 \textit{nums}_2 nums2 的元素和下标信息的二维数组需要 O ( n ) O(n) O(n) 的时间,排序需要 O ( n log ⁡ n ) O(n \log n) O(nlogn) 的时间,排序之后遍历两个数组需要 O ( n ) O(n) O(n) 的时间,因此时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums 1 \textit{nums}_1 nums1 和 nums 2 \textit{nums}_2 nums2 的长度。创建包含 nums 2 \textit{nums}_2 nums2 的元素和下标信息的二维数组需要 O ( n ) O(n) O(n) 的空间。

相关推荐
Logic1013 小时前
C语言/数据结构动态规划题解:Kadane算法求最大子数组和——O(n)时间O(1)空间
c语言·数据结构·动态规划·贪心·时间复杂度·算法题·最大子数组和
伟大的车尔尼2 天前
贪心题目:分发饼干
贪心
Tisfy3 天前
LeetCode 2472.不重叠回文子字符串的最大数目:动态规划(贪心)
动态规划·字符串·题解·贪心·dp·回文字符串
伟大的车尔尼7 天前
贪心题目:三角形的最大周长
贪心
青少儿编程课堂8 天前
贪心算法进阶:区间调度与最少资源整合解析
c++·python·算法·贪心·信息学竞赛·区间调度
伟大的车尔尼11 天前
贪心题目:保持城市天际线
贪心
a1879272183112 天前
【算法】动态规划第三篇:背包第一课——贪心之死与正序倒序开关
算法·leetcode·动态规划·贪心·dp·暴力·算法讲解
lvwangshu15 天前
P7668 [JOI 2018 Final] 团子制作 / Dango Maker 题解
动态规划·题解·贪心·性质题·思维好题
伟大的车尔尼15 天前
贪心题目:玩筹码
贪心