贪心策略:不断循环操作数组arr中的任意两个数,当只剩下1个数,返回这个数可能的最大值

贪心策略:不断循环操作数组arr中的任意两个数,当只剩下1个数,返回这个数可能的最大值

阿里笔试原题
提示:从本文开始,咱们来说贪心策略系列文章!!

贪心策略在互联网大厂的招聘笔试和面试中的地位!!!在笔试中考贪心,而面试不考贪心。

(1)贪心在笔试中:75%的考题都是贪心策略,为啥呢,一方面考你的聪明程度,另一方面,考你的代码编写能力;所以我参加过的笔试证明了这一点,往往大厂给你三个算法题,第1道题一定是贪心,排序结合的算法题,你需要懂点脑子,了解一下排序和堆啥的数据结构,还得会点贪心技巧,才能设计出来;
(2)面试不怎么考贪心策略,为什么?因为面试考你的是算法的优化能力,所以如果给你贪心的话,你一下子想到了解决方案,也不谈什么优化的事情,没意义,所以不考贪心。
(3)你必须要认识到:最简单的是国内的面试过程(嘴说的事情,都好办),难度中上等的是国外的笔试面试,最难的国内的算法笔试。 那么,你一定要明白,最难的还是国内的算法笔试题!!!因此要多练,多学,多见题,多思考,多总结,才能拿下。

以下是贪心策略基础题目系列文章:
(1)贪心策略:请你计算i×arr[i]的累加和最大值
(2)贪心策略:请你设计最优的安排会议日程表,以使得举行的会议数最多
(3)贪心策略:求一条街上最少应该放多少盏灯,才能照亮整条街的商户
(4)贪心策略:请你将字符串拼接,最终拼接好的字符串字典序最小
(5)贪心策略:请你最最小的金条分割代价


题目

本题,和上面的(5),一模一样,本题是阿里的笔试原题
(5)贪心策略:请你最最小的金条分割代价

输入2行,第一行n,代表n个数字,
第二行,就是你要输入的n个数字arr[i],现在对数组进行2种操作:

1)如果有俩相同的数,将其求和,然后sum放入arr;
2)如果俩数不相同,则取两者最大值max,放入arr;
不断循环操作,直到arr中只剩下1个数,返回这个数可能的最大值是多少?


一、审题

示例:
4
4 2 5 4
4和4相同,将其求和,8
放入arr=2 5 8
25不同,求max,5放入arr
arr=5 8
求max,arr=8
8就是结果


二、贪心策略,就是类似哈夫曼树,用小根堆解决

咱们要最后的最大值,那就要从最小值开始操作。

考场上的情况:我1分钟手撕完成,
(1)把arr全部放入小根堆,按照题目中的操作1)2)弹出堆顶的2个,求得cur,
(2)然后cur放入小根堆,循环玩弹出;
当小根堆只剩下1个数,返回它;

比如:
arr = 4 2 5 4
在这里插入图片描述
为什么当时我就想到了这个贪心策略呢?
很简单,在此之前,我见过类似的题目,人还没有说得这么明显呢
(5)贪心策略:请你最最小的金条分割代价

因此见过黄金分割代价最小这个题,就知道哈夫曼树,就是这么操作的。取俩数,然后操作,得到一个结果cur放入堆中,再继续玩
思路前所未有相似:

手撕代码:
这里要注意,真正的大厂笔试题,是输入格式也要你控制的
因为出题的人都是ACM竞赛和极限编程的大佬们,ACM打比赛的题目就是这种输入的格式

Scanner in = new Scanner(System.in);//这是大厂们的输入格式

然后后面不挂你输入字符串,还是字符数组,还是数字数组,都可以这么去读取:

int N = in.nextInt();//输入第一行
        int[] arr = new int[N];
        for (int i = 0; i < N; i++) {
            arr[i] = in.nextInt();//第二行是一个数组
        }
        //有时候可能是一个字符串
        //String s = in.nextLine();//一行读取

本题的代码是:

//阿里巴巴原题:
    //输入2行,第一行n,代表n个数字,
    //第二行,就是你要输入的n个数字arr[i],现在对数组进行2种操作:
    //
    //1)如果有俩相同的数,将其求和,然后sum放入arr;
    //2)如果俩数不相同,则取两者最大值max,放入arr;
    //不断循环操作,直到arr中只剩下1个数,返回这个数可能的最大值是多少?

    public static void maxValue(){
        Scanner in = new Scanner(System.in);//这是大厂们的输入格式
        int N = in.nextInt();//输入第一行
        int[] arr = new int[N];
        for (int i = 0; i < N; i++) {
            arr[i] = in.nextInt();//第二行是一个数组
        }
        //有时候可能是一个字符串
        //String s = in.nextLine();//一行读取

        PriorityQueue<Integer> heap = new PriorityQueue<>();
        for (int i = 0; i < N; i++) {
            heap.add(arr[i]);
        }

        //对比
        while (heap.size() != 1){
            int a = heap.poll();
            int b = heap.poll();

            heap.add(a == b ? a + b : Math.max(a, b));
        }

        System.out.println(heap.peek());
    }

    public static void main(String[] args) {
        maxValue();
    }

测试:

4
4 2 5 4
8

明白了见过贪心的题目之后,今后遇到大厂的题目,是不是就可以尽快有思路了。


总结

提示:重要经验:

1)从本题可以实实在在论证:贪心的题目就是多见题,多思考,多总结,培养敏感度!
2)本题题目说得很直白,要最大值,操作时,取俩数,然后不断对比,再次放入arr,这个过程就可以用哈夫曼树解决,小根堆模拟。
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冰露可乐

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

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

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

打赏作者

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

抵扣说明:

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

余额充值