贪心策略:不断循环操作数组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,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。