通过田忌赛马来了解贪心算法

前言:

大家好,我是Felix。今天我们通过田忌赛马的这样一个生动的例子来了解贪心算法。每当想起这个生动的例子,理解贪心算法就会相对形象一些了。

题意

已知有两个整数数组A,B, 如果A[i] > B[i], 则称A优势于B。请你返回一个A数组的排列,对于B数组的优势最大。

这是原本的题意,但是本质上就是田忌赛马的例子。比如说你和对方都有3匹马,每匹马都有自己的战力,如何对面的出场顺序确定,你如何能够保证自己获得最大的场次呢?

那么关键点是什么呢?

------你要让自己战力最小的马尽可能的赢得比赛,如果无法赢得则直接匹配对方最强的马。

如上图所示,右边是你拥有的马匹,左图是对方的。经过排序之后,你应该要让自己最小的匹配对方最小的,尽量让战力最低的马匹赢得比赛。在这个例子中,6的这匹马,我们应该就要舍弃,去匹配对方最强的马匹35,因为6无论如何它都赢不了的。所以,这个贪心算法就贪在尽量让自己战力低的马匹也能赢。


如何解题呢

思路:

    * 刚才我们已经分析过了,首先这两个数组要进行排序,这样我才容易比较。注意:要保留B数组原本的顺序,因为我们后面获取结果还需要依赖它
    * 我们来遍历排序好的A数组,去匹配排序好的B数组,如果A>B, 这时候,我们应该记录这个A的值,如何记录呢
    * 应该创建一个链表,挂在这个B的值后面,组成一个MAP
    * 如果这个A<B,则我们应该舍弃这个A,放入一个队列,作为被舍弃的马

可能,听起来比较抽象。我们可以看下具体代码。

public class RaceHorses {

    public static void main(String[] args) {
        int [] A = {6, 14, 27, 19, 10};
        int [] B = {9, 35, 17, 13, 7};
        int[] ans = raceHorses(A, B);
        for (int n : ans)
            System.out.print(n + " ");
    }

    public static int[] raceHorses(int [] numsA, int[] numsB) {
        // 对于AB进行排序,但是B要保留原本的顺寻
        int[] cloneB = numsB.clone();
        Arrays.sort(numsA);
        Arrays.sort(numsB);

        // 创建一个保存结果的数组
        int[] ans = new int[numsA.length];


        // 创建一个MAP, key是B的值,value是这个B 可以匹配的值
        // 为啥是个数组呢?
        // 因为B中不能排除有一样的值,这样,维护起来,链表会更加方便

        // 好的,先来初始化这个map
        Map<Integer, LinkedList<Integer>> map = new HashMap<>();
        for (int b: numsB)
           map.put(b, new LinkedList<>());

        // 再创建一个垃圾桶,用来存放无法赢得比赛的
        LinkedList<Integer> bin = new LinkedList<>();

        // 现在来遍历A数组,逐个匹配
        int j = 0;//j 指的是B数组的索引,匹配了就往后走
        for (int i = 0; i < numsA.length; i++) {
            // A匹配上了,放到B对应的结果链表里面
            if (numsA[i] > numsB[j]) {
                map.get(numsB[j]).add(numsA[i]);
                j ++;
            } else {
                //没有匹配上,放入垃圾箱
                bin.add(numsA[i]);
            }
        }

        // 这时候我们维护的map已经出结果了,根据原本B的顺序去生成结果
        for (int i = 0; i < cloneB.length; i++) {
            LinkedList<Integer> queue = map.get(cloneB[i]);
            // 如果QUEUE有元素,说明匹配了,弹出来一个就行
            if (!queue.isEmpty())
                ans[i] = queue.poll();
            // 如果QUEUE没有元素,说明匹配不上,从垃圾桶弹出一个即可
            else
                ans[i] = bin.poll();
        }

        return ans;
    }
}

最后的输出结果:

好啦,今天的算法分享到这里啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值