news 2026/1/30 7:06:15

算法题 优势洗牌

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 优势洗牌

优势洗牌

问题描述

给定两个长度相等的数组nums1nums2,你需要对nums1进行重排列,使得nums1相对于nums2优势最大化。

优势定义:对于索引i,如果nums1[i] > nums2[i],则称nums1在位置i上具有优势。

目标是返回一个nums1的排列,使得优势的总数最大。

示例

输入:nums1=[2,7,11,15],nums2=[1,10,4,11]输出:[2,11,7,15]解释:-nums1[0]=2>nums2[0]=1-nums1[1]=11>nums2[1]=10-nums1[2]=7>nums2[2]=4-nums1[3]=15>nums2[3]=11优势总数为4,是最大可能值。 输入:nums1=[12,24,8,32],nums2=[13,25,32,11]输出:[24,32,8,12]解释:-24>13-32>25-8<=32-12>11优势总数为3

算法思路

贪心策略 + 双指针(田忌赛马)

  1. 核心思想(田忌赛马)

    • nums1刚好能赢nums2中每个元素的最小值
    • 如果nums1中没有能赢nums2[i]的元素,就用最小的元素去输
  2. 为什么这样最优

    • 如果最大值能赢当前nums2元素,那么用最大值是最优的(保留较小的值应对更小的对手)
    • 如果最大值都不能赢,说明任何元素都不能赢,用最小值输掉是最优的(保留大值应对更大的对手)

代码实现

方法一:贪心 + 双指针

importjava.util.*;classSolution{/** * 优势洗牌 - 贪心算法 * * @param nums1 数组1,可以重排列 * @param nums2 数组2,固定不变 * @return nums1的一个排列,使得优势最大化 * * 算法思路(田忌赛马): * 1. 对nums1排序 * 2. 对nums2的索引按值排序(保存原始位置) * 3. 双指针:left指向最小值,right指向最大值 * 4. 对于每个nums2元素(从小到大处理): * - 如果nums1[right] > nums2[i]:用最大值赢 * - 否则:用最小值输 */publicint[]advantageCount(int[]nums1,int[]nums2){intn=nums1.length;// 对nums1进行排序Arrays.sort(nums1);// 创建nums2的索引数组,并按nums2的值排序Integer[]indices=newInteger[n];for(inti=0;i<n;i++){indices[i]=i;}// 按nums2的值升序排序索引Arrays.sort(indices,(i,j)->Integer.compare(nums2[i],nums2[j]));// 结果数组int[]result=newint[n];// 双指针:left指向nums1最小值,right指向nums1最大值intleft=0,right=n-1;// 从nums2最大的元素开始处理(逆序遍历排序后的索引)// 可以优先处理最难赢的元素for(inti=n-1;i>=0;i--){intoriginalIndex=indices[i];// nums2中当前元素的原始位置intnums2Value=nums2[originalIndex];// 如果nums1的最大值能赢nums2的当前最大值if(nums1[right]>nums2Value){// 用最大值赢result[originalIndex]=nums1[right];right--;}else{// 用最小值输(最大值都赢不了,说明所有值都赢不了)result[originalIndex]=nums1[left];left++;}}returnresult;}}

方法二:贪心 + 优先队列

importjava.util.*;classSolution{/** * 使用优先队列 * * @param nums1 数组1 * @param nums2 数组2 * @return 优势最大化的排列 */publicint[]advantageCount(int[]nums1,int[]nums2){intn=nums1.length;// 对nums1排序Arrays.sort(nums1);// 创建最大堆,存储nums2的值和索引PriorityQueue<int[]>maxHeap=newPriorityQueue<>((a,b)->b[0]-a[0]);for(inti=0;i<n;i++){maxHeap.offer(newint[]{nums2[i],i});}int[]result=newint[n];intleft=0,right=n-1;// 从nums2的最大值开始处理while(!maxHeap.isEmpty()){int[]current=maxHeap.poll();intnums2Value=current[0];intoriginalIndex=current[1];if(nums1[right]>nums2Value){result[originalIndex]=nums1[right];right--;}else{result[originalIndex]=nums1[left];left++;}}returnresult;}}

算法分析

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

    • 排序nums1:O(n log n)
    • 排序nums2索引:O(n log n)
    • 双指针遍历:O(n)
    • 总体:O(n log n)
  • 空间复杂度:O(n)

    • 存储索引数组:O(n)
    • 结果数组:O(n)
    • 其他变量:O(1)

算法过程

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

步骤

  1. nums1排序后:[2,7,11,15]
  2. nums2索引按值降序排序:[3(11), 1(10), 2(4), 0(1)]
  3. 双指针:min=0, max=3

过程

  • 处理nums2[3]=11nums1[3]=15 > 11→ 用15赢,result[3]=15max=2
  • 处理nums2[1]=10nums1[2]=11 > 10→ 用11赢,result[1]=11max=1
  • 处理nums2[2]=4nums1[1]=7 > 4→ 用7赢,result[2]=7max=0
  • 处理nums2[0]=1nums1[0]=2 > 1→ 用2赢,result[0]=2max=-1

结果[2,11,7,15],优势数=4

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

步骤

  1. nums1排序后:[8,12,24,32]
  2. nums2索引按值降序排序:[2(32), 1(25), 0(13), 3(11)]
  3. 双指针:min=0, max=3

过程

  • 处理nums2[2]=32nums1[3]=32 <= 32→ 用最小值8输,result[2]=8min=1
  • 处理nums2[1]=25nums1[3]=32 > 25→ 用32赢,result[1]=32max=2
  • 处理nums2[0]=13nums1[2]=24 > 13→ 用24赢,result[0]=24max=1
  • 处理nums2[3]=11nums1[1]=12 > 11→ 用12赢,result[3]=12max=0

结果[24,32,8,12],优势数=3

测试用例

importjava.util.*;publicclassTest{publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:完全优势int[]nums1_1={2,7,11,15};int[]nums2_1={1,10,4,11};int[]result1=solution.advantageCount(nums1_1,nums2_1);System.out.println("Test 1: "+Arrays.toString(result1));// 期望: [2,11,7,15] 或其他优势数为4的排列// 测试用例2:部分优势int[]nums1_2={12,24,8,32};int[]nums2_2={13,25,32,11};int[]result2=solution.advantageCount(nums1_2,nums2_2);System.out.println("Test 2: "+Arrays.toString(result2));// 期望: [24,32,8,12] 或其他优势数为3的排列// 测试用例3:无法获得优势int[]nums1_3={1,2,3};int[]nums2_3={4,5,6};int[]result3=solution.advantageCount(nums1_3,nums2_3);System.out.println("Test 3: "+Arrays.toString(result3));// 期望: 任意排列,优势数为0// 测试用例4:相等元素int[]nums1_4={5,5,5};int[]nums2_4={5,5,5};int[]result4=solution.advantageCount(nums1_4,nums2_4);System.out.println("Test 4: "+Arrays.toString(result4));// 期望: [5,5,5],优势数为0// 测试用例5:单元素int[]nums1_5={1};int[]nums2_5={2};int[]result5=solution.advantageCount(nums1_5,nums2_5);System.out.println("Test 5: "+Arrays.toString(result5));// 期望: [1]// 测试用例6:大数测试int[]nums1_6={10,20,30,40,50};int[]nums2_6={5,15,25,35,45};int[]result6=solution.advantageCount(nums1_6,nums2_6);System.out.println("Test 6: "+Arrays.toString(result6));// 期望: 优势数为5的排列// 测试用例7:重复元素int[]nums1_7={2,0,4,1,2};int[]nums2_7={1,3,0,0,2};int[]result7=solution.advantageCount(nums1_7,nums2_7);System.out.println("Test 7: "+Arrays.toString(result7));}// 计算优势数publicstaticintcountAdvantage(int[]a,int[]b){intcount=0;for(inti=0;i<a.length;i++){if(a[i]>b[i])count++;}returncount;}}

关键点

  1. 田忌赛马

    • 用最弱的马对最强的马(如果赢不了)
    • 用刚好能赢的马对对手的马(如果能赢)
  2. 贪心选择

    • 如果最大值能赢当前最大值,那么用最大值是最优的
    • 如果最大值不能赢,那么任何值都不能赢,用最小值是最优的
  3. 索引排序

    • 需要保持nums2元素的原始位置信息
    • 按值排序索引可以按特定顺序处理元素
  4. 处理顺序

    • nums2的最大值开始处理
    • 可以优先处理最难赢的元素,做出最优决策

常见问题

  1. 为什么要从最大值开始处理?

    • 最大值是最难赢的对手
    • 优先处理最难的情况可以避免浪费大值在容易赢的对手上
  2. 为什么不能从小到大处理?

    • 从小到大处理可能导致:用大值赢了小对手,结果面对大对手时没有足够的大值
    • 从大到小处理确保了资源的最优分配
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/30 1:21:46

前端开发工具,零基础入门到精通,收藏这篇就够了

在本文中&#xff0c;我为前端Web开发人员汇总了26种顶级工具&#xff0c;从代码编辑器和代码游乐场到CSS生成器、JS库等工具&#xff0c;为您的职业与工作保驾护航。篇幅较长&#xff0c;可以收藏随时拿出来看。 目录 CSS代码生成器 CSS3 Generator 终极CSS Generator CS…

作者头像 李华
网站建设 2026/1/25 19:09:45

OwlLook小说搜索引擎终极指南:快速搭建个人专属阅读库

OwlLook小说搜索引擎终极指南&#xff1a;快速搭建个人专属阅读库 【免费下载链接】owllook owllook-小说搜索引擎 项目地址: https://gitcode.com/gh_mirrors/ow/owllook 你是否曾经为找不到心仪的小说资源而烦恼&#xff1f;是否厌倦了在不同网站间来回切换的繁琐操作…

作者头像 李华
网站建设 2026/1/26 2:32:48

3D图像匹配技术实战指南:从零掌握MASt3R核心应用

3D图像匹配技术实战指南&#xff1a;从零掌握MASt3R核心应用 【免费下载链接】mast3r Grounding Image Matching in 3D with MASt3R 项目地址: https://gitcode.com/GitHub_Trending/ma/mast3r 在计算机视觉领域&#xff0c;3D图像匹配技术正成为增强现实、机器人导航和…

作者头像 李华
网站建设 2026/1/17 20:26:47

大数据课程实践:基于朴素贝叶斯算法的购车意向预测分析

一、项目概述与背景 1.1 项目简介 本项目是《大数据数据分析与应用》课程的实践环节&#xff0c;旨在通过真实的汽车客户数据集&#xff0c;应用朴素贝叶斯分类算法构建购车意向预测模型&#xff0c;展示从数据预处理到模型评估的完整机器学习流程。 1.2 技术栈 编程语言&am…

作者头像 李华