说明(个人见解): 一、标注说明 标注手撕:必须掌握,熟练写出 code; 标注星号:星号越多越重要; 标注加分:一般此类都是算法不容易实现,但是需要掌握思想,面试加分。 二、刷题顺序 1、了解基本的数据结构与算法的知识:
- 常用的数据结构:数组、链表、栈、队列、哈希表、树、图等的基本概念和实现;
- 常用的算法:DFS / BFS、最短路径算法(Dijkstra)、贪心算法、动态规划、蓄水池算法、Manacher 算法等;
- 常用的编程技巧:递归:递归非常重要,要认真理解递归的过程;
2、《剑指Offer》: 《剑指Offer》非常重要,可以看各大公司的面经,很多手撕代码都出自于《剑指Offer》,所以多刷几遍,每一题都务必能快速的手写出来。 3、LeetCode: 《剑指Offer》刷完了,可以先刷 LeetCode 的 Top100,当然你也可以根据自身的情况,刷自己薄弱的专题。大部分公司的笔试题都是出自于 LeetCode,原题或者改编,重要性就不用多说了; 4、左神算法班: 这个因人而异了,如果你对算法题比较敏感,这个阶段是可以跳过的。但是如果对算法不是很有信心或者准备的比较晚,还是比较推荐左神的算法班,分为初级和高级,会串讲基本的数据结构和对应的题目。 5、最后: 算法的重要性:得算法者得 Offer。大公司非常看重算法,即便内推,但是面试环节几乎都会手撕代码,如果这个环节出了问题,会大打折扣。
一、基础数据结构篇
排序
查找
前缀树
二、实战篇
1、数组
1、找出数组中出现次数大于数组长度一半和 N / K 的数【剑指Offer + 左神】【手撕】
2、数组的奇偶位置问题:给定一个整型数组,请在原地调整这个数组,保证要么偶数位置上都是偶数,或者奇数位置上都是奇数。
3、调整数组顺序使奇数位于偶数前面【剑指Offer】【手撕】
4、数组的度(字节跳动面试题 + LeetCode)
5、求一个数组中的第 k 小 / 大的数【BFPRT 算法、快排】【手撕】
6、将一个整数数组划分为K个相等的子集问题【LeetCode + 字节跳动面试题】
7、旋转数组中的最小数字【剑指Offer】
8、在二维数组中查找一个数【剑指Offer】
9、找出数组中重复的数字【剑指Offer】
10、找出数组中只出现一次的那个数,其他都出现两次【字节跳动面试题】
11、子数组问题:在条件下,每一个位置的元素都会作为子数组的开头或者结尾元素,那么遍历完整个数组,结果一定在其中
- 子数组最大累乘积:给定一个 double 类型的数组 arr,其中的元素可正、可负、可 0,返回子数组累乘的最大乘积。
- 需要排序的最短子数组长度
- 最长的可整合子数组的长度
- 最短无序连续子数组:双指针实现【LeetCode】
- 连续子数组的最大和【剑指Offer】:推荐动态规划实现【手撕】
2、字符串
1、字符串的排列与组合【手撕】
2、最长回文子串:暴力+动态规划+Manacher算法【手撕:推荐用动态规划】
3、正则表达式匹配:实现一个函数用来匹配包括’.’和’*’的正则表达式【剑指Offer】
4、替换空格【剑指Offer】
5、字符串的翻转和旋转及其应用【三步翻转法】
6、字符串解码【华为笔试题 + LeetCode】
7、无重复字符的最长子串【LeetCode】
8、字符串的最长公共子串和最长公共子序列
9、请实现一个函数用来判断字符串是否表示数值【剑指Offer】
10、判断一个字符串是否是一个合法的 IPV4【美团面试题】
3、哈希表
1、手写一个简单的 HashMap【手撕】
2、和为 K 的子数组:给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数【LeetCode】
3、一种接收消息并按顺序打印的结构设计:单链表 + 两个HashMap【左神】
4、哈希表增加 setAll 功能【左神】
4、栈
1、用固定大小的数组实现栈
2、如何仅用队列实现栈【手撕】
3、最小值栈:能够返回栈中最小元素的栈【剑指Offer:包含 min 函数的栈】
4、栈的压入、弹出序列:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序【剑指Offer】
单调栈结构问题
5、队列
1、用固定大小的数组实现队列
2、如何仅用栈结构实现队列【手撕】
6、链表
1、反转单向链表【*】
2、反转双向链表
3、K 个一组翻转链表(字节跳动面试题)
4、合并两个排序的链表【剑指Offer】【*】
5、链表中倒数第 K 个节点【剑指Offer】【*】
6、O(1) 时间内删除一个节点【剑指Offer】
7、删除链表中重复的节点【剑指Offer】
8、从尾到头打印链表【剑指Offer】
9、判断一个链表是否为回文结构【剑指Offer】
10、给出两个有序链表的头结点,打印出两个链表中相同的元素
11、将单向链表按某值划分成左边小、中间相等、右边大的形式【荷兰国旗问题】
12、复制含有随机指针节点的链表
13、两个单链表相交的一系列问题【*】
14、链表中环的入口节点【剑指Offer】【*】
15、复杂链表的复制【剑指Offer】**
7、树
1、二叉树的遍历:
- 1、二叉树的前序、中序、后序遍历的递归实现【手撕】
- 2、二叉树的前序、中序、后序遍历的非递归实现【手撕】
- 3、二叉树的层序遍历【从上到下打印一棵二叉树(剑指Offer)】【手撕】
- 4、Morris 遍历二叉树:前序、中序、后序【二叉树的最优遍历:时间复杂度 O(N)、额外空间复杂度 O(1)】【左神】
- 5、输入一个数组,判断是不是二叉搜索树的后序遍历序列
2、二叉树的序列化与反序列化【剑指Offer】:
3、在二叉树中找一个节点的后继节点
4、判断一棵树是否是完全二叉树:层序遍历结合完全二叉树的特点
5、判断一棵树是否是搜索二叉树:中序遍历结果升序
6、判断一棵树是否是平衡二叉树:左平衡 && 右平衡 &&(左右高度差小于1)
7、判断一棵树是否是对称的二叉树【剑指Offer】
8、二叉树的镜像【剑指Offer】
9、树的子结构:输入两棵二叉树A和B,判断B是不是A的子结构
10、合并二叉树【LeetCode】
11、二叉树中和为某一值的路径【剑指Offer】
12、重建二叉树:输入某二叉树的前序遍历和中序遍历的结果,请重新构造出该二叉树【剑指Offer】
13、求一棵完全二叉树的节点个数,时间复杂度低于O(N):结合满二叉树特点:2 ^ h - 1
14、找二叉树左下角的值【LeetCode】
15、把二叉搜索树转换为累加树(百度面试题)【LeetCode第538题】
16、二叉树信息收集问题:
8、图
1、深度优先搜索
2、广度优先搜索
3、拓扑排序
9、数字与位运算
1、两数之和、三数之和【LeetCode】【手撕】
2、大数问题:大数相加和大数相乘问题 + Karatsuba 算法【手撕】
3、打印从 1 到最大的 n 位数:需要考虑大数问题【剑指Offer】
4、数值的整数次方【剑指Offer】
5、二进制中 1 的个数【剑指Offer】【手撕】
10、排序的应用
快排的应用:
- 1、求一个数组中的第 K 小 / 大的数【手撕】
- 2、最小的 K 个数【手撕】
归并排序的应用:
11、矩阵问题
1、顺时针打印矩阵
2、将一个正方形旋转90度
3、之字型打印矩阵
4、在一个行和列都有序的 m 行 n 列的矩阵中查找一个数是否存在
12、递归
1、求 n! 的结果
2、汉诺塔问题【手撕】
3、打印一个字符串的全部子序列,包括空字符串
4、打印一个字符串的全排列
5、母牛问题:母牛每年生一只母牛,新出生的母牛成长三年后也能每年生一只母牛,假设不会死。求 N 年后,母牛的数量
6、机器人走路问题【递归+动态规划】
7、给定一个数字组成的字符串,返回有多少种合法的 IPV4 组合【递归+动态规划】
13、动态规划
1、机器人走路问题【递归+动态规划】
2、给定一个数字组成的字符串,返回有多少种合法的 IPV4 组合【递归+动态规划】
3、矩阵最小路径问题:二维数组从左上角走到右下角的最短距离【手撕】
4、剪绳子:剪成 m 段,最大乘积问题【剑指Offer】
背包问题:
14、贪心算法
1、按最低字典序拼接字符串
2、切分金条总代价最小
3、最多做 K 个项目的最大利润
4、安排最多的宣讲场次
15、回溯算法
16、经典结构
1、单调栈结构【见3】
2、滑动窗口结构
17、经典算法
1、蓄水池算法:解决等概率问题【多益网络笔试题】
2、Manacher 算法:解决回文串问题
3、KMP 算法:解决字符串匹配问题:时间复杂度为:O(N + M),空间复杂度为:O(M)
4、BRPRT 算法:解决第 k 大数问题:选择中位数组的中位数作为 partition 的基准,时间复杂度 O(N)
5、单例模式:懒汉+恶汉+静态内部类+双重校验锁【手撕】
6、生产者消费者模式:wait/notify 、BlockingQueue 实现【手撕】
7、多个线程交替打印:锁、信号量 Semaphore 实现【手撕】
18、剑指 Offer
《剑指Offer》中不容易分类的题目,在这里单独列出:
第36题:二叉搜索树与双向链表:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表
第41题:数据流中的中位数:两个堆实现:最大堆和最小堆
19、LeetCode
LeetCode 中不容易分类的题目,在这里单独列出: