优势洗牌(田忌赛马)——贪心算法


一、题目描述

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、题目分析

算法

比如
A:{2,8 ,3 ,6}
B:{4,7,9,1}
让A去比较B下标为0的元素4,选取A中比B大的,即{8,6 },让8去比还是6去比呢?
需要拿较小的去比,因为较大的8,可能后面会用到,比如和B的7比。
这就相当于选取A中比B大且刚刚大于的元素,就达到了局部最优,下一次比较同样是寻找刚大于的元素,也是局部最优。
即所有局部最优得到全局最优。就想到了贪心算法,

数据结构

每次选取A中比B大且刚刚大于的元素,达到局部最优,如果先将A由小到大A排序,每次与B比较,只需要遍历A即可,找到比B大且刚刚大于的元素,这个元素就是与B完美配对的,与B中下一个元素比较时就用不到了,删除即可。
A排序后:{2,3,6,8}
B: {4,7,9,1}
开始配对:

  • 从头遍历A,配对4——>6,删除A中元素6,
  • 从头遍历A,配对7——>8,删除A中元素8
  • 从头遍历A,9配对失败
  • 从头遍历A,配对1——>2,删除A中元素2
  • 那么A中剩余的元素就是3

这样只排序A的话,每次与B中一个元素比较,都要从头遍历A。

如果将B也排序:
A排序后:{2,3,6,8}
B排序后:{1,4,7,9}
开始配对:

  • 从头遍历A,配对1——>2
  • 从上次配对结束的地方开始遍历,3配对失败,6配对成功,配对4——>6
  • 从上次配对结束的地方开始遍历,配对7——>8
  • B中剩下9,A中的元素剩下的都比9小

其实A中配对失败元素就是剩下的元素,比B剩下的元素小,直接将A中配对失败元素放入另一个队列或栈中,最后将其出队与B剩下的元素随意配对。

注意:题目要求A随意排列,但B元素下标是固定的,那就需要复制数组B为bsort数组,来辅助与A配对,将B数组每个元素设置为头结点,然后找到该bsort元素在B中的位置,最后将bsort的元素与A配对成功的元素链接在B后面(配对)

最终A中配对元素的顺序就是遍历B中每个链表元素的顺序。

在这里插入图片描述

代码

    public static int[] advantageCount(int[] A,int[] B){
        int[] sortB = B.clone();
        Arrays.sort(sortB);
        Arrays.sort(A);

        Map<Integer, Deque<Integer>> bMap = new HashMap<>();
        for (int b : B){
            bMap.put(b,new LinkedList<>());
        }
        Deque<Integer> aq = new LinkedList<>();
        int j = 0;
        for (int a : A){
            if (a > sortB[j]){
                bMap.get(sortB[j++]).add(a);
            }else {
                aq.add(a);
            }
        }
        int[] ans = new int[A.length];
        for (int i = 0;i<B.length;i++){
            if(bMap.get(B[i]).size()>0){
                ans[i] = bMap.get(B[i]).removeLast();
            }else {
                ans[i] = aq.removeLast();
            }
        }
        return ans;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Strive_LiJiaLe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值