刷算法的重要性
首先说一下刷算法题的重要性,大厂基本上每一轮的技术面试都会涉及到算法的考察。
如果算法题写不出来,大概率无法通过面试。换句话说,想进大厂,算法题是必刷的。
接着,我们先来看一下刷题要求,从时间上来说,在你学完一门语言的基础语法之后,
就可以开始刷算法题了,不要等着找工作的时候才开始,算法是需要一个长期的过程,
而不是像八股文一样,可以速成。另外,推荐或者说是要求大家使用自己的主语言进行刷题。可以想象,如果你是一个Java选手,却使用C++来写算法题,面试官会觉得你的Java基础不牢靠。当然了,作为一个学生,我也理解大家使用C++的原因,首先就是学校一般是先学C++,后学Java。包括数据结构与算法,也是C或者C++版本的,但是,一定要自己有意识的去使用主语言刷题。
刷题路线
然后说一下刷题路线,对于算法零基础或者说只学习过数据结构而没有系统刷题的同学来说,建议从基础到进阶,最后进行冲刺。基础篇中,推荐大家通过算法通关村或者代码随想录,进行学习。说一下我自己的学习情况。我在刷题的时候,前面的简单部分是通过算法通关村进行刷题的。算法通关村一共分为20个关卡,每个关卡分为青铜、白银、黄金三个等级。内容上分为数据结构,模板,算法,三大部分。推荐大家在刷题的时候也进行打卡,我在csdn置顶文章中,放了我各个 关卡的打卡目录,大家有时间可以去看看,我的csdn名称也是今天不coding,主要是看需要刷哪些题就好了。我的打卡比较简单,写了一些题目,答案和思路。最后整理出目录也是比较有成就感的。还获得了当时算法通关村村长的表扬,然后拿到了一本算法书籍。剑指offer。
秋招遇到的算法题
下面给大家介绍一下秋招过程中,我和我的室友遇到的算法相关的问题。
首先是链表,如果你前面的八股和算法回答的不错,那么大概率最后会给你出一道简单的链表题走个流程,链表这一部分,考过的问题如下:包括反转链表、两个链表的第一个公共子节点、寻找链表的中间节点、重排链表、合并两个升序链表、环形链表。数组,这部分要注意双指针思想的使用,包括快慢型双指针和对撞型双指针。但是没有考过我,主要是问过我数组中出现次数超过一半的元素,以及螺旋矩阵这两个问题。栈和队列没有单独考察。通常是作为工具在其他的算法题中使用哈希这里三数之和考过一次,LRU我要是不说你肯定猜不到,在我秋招20多次的大厂面试中,考了四次。所以,这个题一定要会写啊。二叉树这里也问我问的比较简单吧,只考过判断两棵树是否对称和最大深度以及层次遍历的简单问题。后是模版,位运算这里考过我使用位运算进行乘法的实现,有一说一,这个我没写出来。字符串考过一道大整数乘法,堆这里考过合并K个升序链表,其实,合并K个升序链表有很多种方法,但是使用堆来实现是比较简单的。海量数据存储包括位图,分块,和堆。这里考过我一个使用小内存实现查找海量数据中出现次数最多的元素问题。快速排序和二分查找,国企的技术岗考过好多次,一般就是直接让给你写这两个算法的实现。大厂面试中,考过我一道有序数组转化为二叉搜索树的问题。滑动窗口考过无重复的最长子串,贪心考过跳跃游戏问题,我们平时刷题大概率只会刷到跳跃游戏I和II,当时考的是IV,没做出来。回溯这里的高频题就是有效的IP地址,动态规划也考的比较简单,只问过我爬楼的方法和存在障碍物的路径中的有效路径数目。对于贪心,回溯,动态规划这三部分比较难的算法题来说,建议大家看程序员卡尔的视频,讲的非常好,非常清楚。后面就是看自己的时间了,leetcode最少要保证把hot100刷完,有时间可以刷前两百,前三百。开始准备秋招面试之前,就开始刷codetop。面向大厂高频题,效率更高。
Java刷题用到的数据结构和方法
然后给大家分享一下,刷题过程中会用到的一些数据结构和对应的方法,需要简单记忆一下,因为刷题的时候需要我们在没有代码提示的环境下完成。
栈
Stack stack = new Stack<>();
stack.isEmpty();
stack.push();
stack.pop();
stack.peek();
Deque stack = new LinkedList();
stack.isEmpty();
stack.push();
stack.pop();
stack.peek();
队列
Queue queue = new LinkedList();
queue.offer();
queue.poll();
queue.isEmpty();
queue.peek();
queue.size();
双端队列
Deque deque = new LinkedList();
deque.pollFirst();
deque.pollLast();
deque.offerFirst();
deque.offerLast();
HashMap
Map<Integer,Integer> map = new HashMap<>();
map.containsKey()
map.put()
map.get()
map.keySet()
HashSet
Set set = new HashSet<>();
set.add()
set.remove()
Integer[] array = set.toArray(new Integer[set.size()])
String
字符串转字符数组
char[] chars = s.toCharArray();
字符数组转字符串
String str = new String(chars);
堆/优先队列
小顶堆/大顶堆
PriorityQueue minHeap = new PriorityQueue((a, b) -> a - b);
PriorityQueue maxHeap = new PriorityQueue((a, b) -> b - a);
指定容量的堆
PriorityQueue heap = new PriorityQueue(k,(a, b) -> b - a);
heap.offer();
heap.poll();
heap.isEmpty();
heap.peek();
数组
Arrays.equals(int[] num1,int[] num2);
Arrays.copyOfRange(nums,start,end);
res.stream().mapToInt(i->i).toArray();
刷题技巧
最后说一下刷题技巧,先说刷题难点,开始难,不知道如何下手,打开leetcode第一题两数之和,不会,从入门到放弃。针对这个问题就是按照刚才说的路线去刷,从最简单的链表开始,20天的时间,逐层深入。然后是中间,数据结构的部分难度都还可以,第一个难关是递归。我甚至觉得递归的难度超过动态规划。动态规划是懂了这个题,但是不懂这一类题。递归的难点就在于理解不了,不知道在干什么,这个题都解决不了。针对这个问题,除了所谓的画图理解之外,就是抄代码,我大概抄了50多道题,抄了三遍之后,就能写了,也有了自己的理解,反正就是边抄边体会就好,这里多花点时间也无所谓。最后是结尾的难题,贪心、回溯和动态规划。看视频,把每一个都看懂就好啦,不用举一反三,只要把讲过的题目都看过就好了。然后才开始真正的技巧,第一点就是按照类别去刷,这个不多说了。第二点就是写思路打卡,既是为了能够保证刷题的进度,也是做好记录,等自己以后忘了可以回看,自己写的东西,往往自己印象深刻,不容遗忘,忘了也能在很短的时间内捡起来。最后就是要数量更要质量。不要盲目的追求500+,800+,只要掌握常见的题型就可以啦。我自己是300左右,leetcode hot100
每一道题至少刷三次,还有的刷了四五次,前三百,除了很少一部分题,其他的也都刷了两遍。