0. 方法
- 按从低到高的难度分组刷
- 按 tag 分类刷
- 定期复习,重做之前刷过的题
- 可以看一看
1. 数据结构
1.1 栈
| 题目 | 难度 | 时间+代码 | 思路 | 知识点 |
|---|---|---|---|---|
| 20. 有效的括号 | 易 | 2020年11月3日 | 左括号进栈,右括号出栈,并用switch判断 | |
| 155. 最小栈 | 易 | 2020年11月3日 | 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈 | |
| 法1:多开一个栈来存min | ||||
| 法2:Better 解法2 省一点空间,只用1个栈 + 1点技巧 | ||||
| 225. 用队列实现栈 | 易 | 2020年11月4日 | 取巧一下:先出队再重新进 | ① 队列:先进先出。队头出,队尾进 |
| ② 栈:先进后出。只能从栈顶进、出 | ||||
| ③ 所以,进栈容易,出栈比较麻烦。 | ||||
| 232. 用栈实现队列 | 易 | 2020年11月5日 | 法1:两个栈实现先入先出队列 | |
| 法2:better 一个专门输入,一个专门输出;并用front记住队头变量,可以直接peek() | ||||
| 496. 下一个更大元素 I | 易 | 2020年11月5日 | 单调栈解决 Next Greater Number 一类问题 | 用HashMap提高查找效率 |
| 682. 棒球比赛 | 易 | 2020年11月6日 | 用栈很容易实现,跟后缀表达式求值有点像 | java字符串和数字相互转换 |
| String字符串相等判断 | ||||
| 1021. 删除最外层的括号 | 易 | 2020年11月6日 | Better 不用栈,用在线检测 | for each |
| 1047. 删除字符串中的所有相邻重复项 | 易 | 2020年11月7日 | 使用StringBuilder来模拟栈 | StringBuilder |
| 1441. 用栈操作构建数组 | 易 | 2020年11月7日 | 读懂题意即可 | List<String> list = new ArrayList<>(); |
| 1544. 整理字符串 | 易 | 2020年11月8日 | 读懂题意即可 | 大小写字母ASCII码之间的关系:'a' - 'A' = 32, 'a' - 'z' = -25 |
for (char c : s.toCharArray()) | ||||
| 1598. 文件夹操作日志搜集器 | 易 | 2020年11月8日 | 法1:栈,空间复杂度O(n) | |
| 法2:受到法1过程的启发,不需要用栈,空间复杂度O(1) | ||||
1.2 队列
| 题目 | 难度 | 时间+代码 | 思路 | 知识点 |
|---|---|---|---|---|
| 933. 最近的请求次数 | 易 | 2020年11月9日 | 超过范围的出队即可 | Queue<Integer> queue = new LinkedList<>(); |
| 剑指 Offer 59 - I. 滑动窗口的最大值 | 易 | 2020年11月9日 | 单调队列 | 单调队列是一个双端队列 |
1.3 树
| 题目 | 难度 | 时间+代码 | 思路 | 知识点 |
|---|---|---|---|---|
| 94. 二叉树的中序遍历 | 2020年10月21日 | ? | ||
| 100. 相同的树 | 易 | 2020年11月14日 | 递归 | |
| 101. 对称二叉树 | 易 | 2020年11月14日 | 递归 | 找到对称的规律:① 左的左 = 右的右 ② 左的右 = 右的左 |
| 104. 二叉树的最大深度 | 易 | 2020年11月15日 | 递归 | 树的深度 = max {左子树深度, 右子树深度} + 1 |
| 102. 二叉树的层序遍历 | 易 | 2020年11月15日 | 广度优先需要用队列作为辅助结构。先将根节点放到队列中,然后不断遍历队列 | 广度优先搜索算法(Breadth-First-Search) |
| 107. 二叉树的层次遍历 II | 易 | 2020年11月16日 | 在上一题的基础上简单修改即可。主要是逆序输出。 | res.add(0,tmp); //为了逆序输出,采用链表,并添加到头部 |
| 108. 将有序数组转换为二叉搜索树 | 易 | 2020年11月16日 | 讲解:构造二叉搜索树。代码 | 二查搜索树、树的构造、中序遍历 |
| 110. 平衡二叉树 | 易 | 2020年10月22日,2020年11月19日 | 需要遍历所有节点:根、左、右 | 先序遍历(递归)、树的高度(递归) |
| 111. 二叉树的最小深度 | 易 | 2020年11月19日 | 理解递归结束条件 | |
| 112. 路径总和 | 易 | 2020年11月20日 | 不需要知道具体路径:DFS 深度优先搜索 | |
| 2020年11月21日 | 若需要知道具体路径:稍改一下代码,加一个List记录每个节点的值 | |||
| 226. 翻转二叉树 | 易 | 2020年11月21日 | 读懂题意即可 | |
| 235. 二叉搜索树的最近公共祖先 | 易 | 2020年11月21日 | 利用二叉搜索树的特点,递归 | |
| 257. 二叉树的所有路径 | 易 | 2020年11月22日 | 构造辅助函数:基于深度搜索。并利用好传入参数 | |
| 404. 左叶子之和 | 易 | 2020年11月22日 | 递归求解。增加一个参数,标志是其父节点的左儿子(-1)还是右儿子(1),以辅助判断叶子是不是左叶子 | 递归的返回值 |
| 501. 二叉搜索树中的众数 | 易 | 2020年11月22日 | [// 二查搜索树的中序遍历是一个有序的数组 // 为了统计出现的频次,需要知道当前值是否跟上一次的值一致 // 当前频次count, 最大的频次maxCount](// 二查搜索树的中序遍历是一个有序的数组 // 为了统计出现的频次,需要知道当前值是否跟上一次的值一致 // 当前频次count, 最大的频次maxCount) | for循环把 ArrayList<Interger> 转成 int[] |
| 530. 二叉搜索树的最小绝对差 | 易 | 2020年11月22日 | // 二查搜索树的中序遍历是有序的 // minDif 记录已知的最小值 | int min = Integer.MAX_VALUE; |
| 543. 二叉树的直径 | 易 | 2020年11月22日 | 与之前的知识联系起来:树的高度,后序遍历 | |
| 563. 二叉树的坡度 | 易 | 2020年11月22日 | 后序遍历 | 利用好递归函数的返回值,以及类的变量 |
| 572. 另一个树的子树 | 易 | 2020年11月22日 | ① 遍历树s,先把树s中跟t节点一样的节点全部找出来 (递归1);② 然后逐个判断是否是完全一样的树 (递归2) | |
| 606. 根据二叉树创建字符串 | 易 | 2020年11月23日 | 分析清楚规律,做好特殊情况处理,递归。 | 不直接用String去相加,因为String的内容不可修改,每次都是重新生成,底层用的是StringBuffer。Better:采用StringBuiler,而且sb.append(...) |
注意Java的字符串是用双引号"",而单引号''表示的是字符char | ||||
| 617. 合并二叉树 | 易 | 2020年11月23日 | 分情况讨论,递归 | |
| 559. N叉树的最大深度 | 易 | 2020年11月24日 | 读懂题意即可。递归 | for (Node child : root.children) |
| 589. N叉树的前序遍历 | 易 | 2020年11月24日 | 读懂题意即可。递归 | |
| 590. N叉树的后序遍历 | 易 | 2020年11月24日 | 读懂题意即可。递归 | |
| 637. 二叉树的层平均值 | 易 | 2020年11月25日 | 层次遍历 | Queue<TreeNode> queue = new LinkedList<>(); |
double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;也是Java的默认浮点数类型 | ||||
long 数据类型是 64 位、有符号的以二进制补码表示的整数; | ||||
int、float 是32位 | ||||
| 653. 两数之和 IV - 输入 BST | 易 | 2020年11月25日 | 使用 HashSet | HashSet Set <Integer> set = new HashSet(); set.add(x); set.contains(x); |
| 669. 修剪二叉搜索树 | 易 | 2020年11月26日 | 递归,想清楚返回值应该是什么 | public TreeNode trimBST(TreeNode root, int low, int high) { |
| 671. 二叉树中第二小的节点 | 易 | 2020年11月26日 | 递归,并记录min, secondMin, secondMinFlag | |
| 700. 二叉搜索树中的搜索 | 易 | 2020年11月27日 | 读懂题意即可,很简单 | |
| 783. 二叉搜索树节点最小距离 | 易 | 2020年11月27日 | 同 530. 二叉搜索树的最小绝对差 | |
| 872. 叶子相似的树 | 易 | 2020年11月27日 | 分别遍历并用数组存,再对比 | |
| 897. 递增顺序查找树 | 易 | 2020年11月27日 | 先中序遍历存进数组,再构造新的树 | |
| 938. 二叉搜索树的范围和 | 易 | 2020年11月27日 | 可利用二叉搜索树的特点加速 | |
| 965. 单值二叉树 | 易 | 2020年11月27日 | ||
| 2020年11月27日 | 学一下不用构造辅助函数的递归写法 | |||
| 993. 二叉树的堂兄弟节点 | 易 | 2020年11月28日 | 层序遍历。注意理解题意中的“深度”,不是高度 | |
| 1022. 从根到叶的二进制数之和 | 易 | 2020年11月29日 | 用一个变量cur维护到达当前节点时所记录的十进制数 | |
| 面试题 04.02. 最小高度树 | 易 | 2020年11月29日 | 再做一遍,同 108. 将有序数组转换为二叉搜索树 | |
| 面试题 04.04. 检查平衡性 | 易 | 2020年11月30日 | 再做一遍,同 110. 平衡二叉树 | |
| 剑指 Offer 27. 二叉树的镜像 | 易 | 2020年10月23日,2020年11月30日 | 读懂题意即可 | |
| 剑指 Offer 28. 对称的二叉树 | 易 | 2020年11月30日 | 再做一遍,同 101. 对称二叉树 | |
| 剑指 Offer 32 - II. 从上到下打印二叉树 II | 易 | 2020年11月30日 | 再做一遍,同 102. 二叉树的层序遍历 | List<List<Integer>> res = new ArrayList<List<Integer>>(); |
| 剑指 Offer 55 - I. 二叉树的深度 | 易 | 2020年11月30日 | 再做一遍,同 104. 二叉树的最大深度 | |
| 剑指 Offer 54. 二叉搜索树的第k大节点 | 易 | 2020年11月30日 | // 二叉搜索树的中序遍历是递增的 // 那么反过来,右、中、左,则得到的是递减的。这样就不需要遍历所有节点,也可以找到第k大的节点 | |
| 剑指 Offer 55 - II. 平衡二叉树 | 易 | 2020年11月30日 | 再做一遍,同 110. 平衡二叉树 | |
| 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 | 易 | 2020年11月30日 | 再做一遍,同 235. 二叉搜索树的最近公共祖先 | |
| 剑指 Offer 68 - II. 二叉树的最近公共祖先 | 易 | 2020年11月30日 | 后序遍历 DFS | |
| 面试题 17.12. BiNode | 易 | 2020年12月1日 | 笨方法:直接做 | |
| 2020年12月1日 | 二查搜索树的中序遍历是递增的;在遍历过程中,修改每一个根节点的左右指向,实现原址修改 | |||
1.4 堆
| 题目 | 难度 | 时间+代码 | 思路 | 知识点 |
|---|---|---|---|---|
| 剑指 Offer 40. 最小的k个数 | 易 | 2020年11月7日 | Better 用大根堆 | PriorityQueue 默认是小根堆,实现大根堆需要重写一下比较器 |
Queue<Integer> pq = new PriorityQueue<>((v1, v2) -> v2 - v1); | ||||
| 2020年12月1日 | 大根堆 | int[] array = new int[0]; // 定义一个长度为 0 的数组 / 空数组 | ||
| 内置排序算法 | Arrays.sort(arr); | |||
| 快排? | ||||
| 703. 数据流中的第 K 大元素 | 易 | 2020年12月3日 | 小根堆 | |
| 1046. 最后一块石头的重量 | 易 | 2020年12月3日 | 大根堆 | |
大根堆
法 1:重写比较器
Queue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return 0;
}
});
法 2:
Queue<Integer> pq = new PriorityQueue<>((v1, v2) -> v2 - v1);
1.5 集合
| 题目 | 难度 | 时间+代码 | 思路 | 知识点 |
|---|---|---|---|---|
| 349. 两个数组的交集 | 易 | 2020年12月5日 | 两个HashSet | |
2. 算法
2.1 贪心算法
| 题目 | 难度 | 时间+代码 | 思路 | 知识点 | ||||
|---|---|---|---|---|---|---|---|---|
| 122. 买卖股票的最佳时机 II | 易 | 2020年12月14日 | 自己按照推理写出来的。其实本质上是贪心算法,只是没有找到规律。 | |||||
| 2020年12月14日 | 这道题 「贪心」 的地方在于,对于 「今天的股价 - 昨天的股价」,得到的结果有 3 种可能:① 正数,② 00,③负数。贪心算法的决策是: 只加正数 | |||||||
| 455. 分发饼干 | 易 | 2020年12月14日 | 设计好贪心的策略即可 | |||||
| 392. 判断子序列 | 易 | 2020年12月17日 | 双指针 | // 特殊情况提前处理;// 避免一直查询字符串长度 | ||||
| 135. 分发糖果 | 难 | 2020年12月17日 | 贪心算法,两边遍历 | |||||
| 435. 无重叠区间 | 中 | 2020年12月19日 | 贪心算法 · 区间调度问题:图解 | |||||
| 452. 用最少数量的箭引爆气球 | 中 | 2020年12月19日 | 在435. 无重叠区间的基础上修改 | ![]() | ||||
int数据类型是32位、有符号的以二进制补码表示的整数;最小值是 -2,147,483,648 (-2^31);最大值是 2,147,483,647 (2^31 - 1) | ||||||||
| 在计算机系统中,数值一律用补码来表示和存储,就是取反后加1。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理 | ||||||||
| 605. 种花问题 | 易 | 2020年12月19日 | 贪心算法 + 常数优化 | 学习判断条件的写法:`if ( flowerbed[i] == 0 && (i == 0 | flowerbed[i - 1] == 0) && (i == flowerbed.length - 1 | flowerbed[i + 1] == 0) )`,解决边界情况的判断 | ||
| 763. 划分字母区间 | 中 | 2020年12月20日 | 贪心算法 + 双指针 | |||||
| 406. 根据身高重建队列 | 中 | 2020年12月21日 | 先排序再插入 图解及套路总结 | Arrays.sort(people, (o1, o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0]); // 自定义排序 | ||||
return list.toArray(new int[list.size()][2]); // 链表LinkedList<int[]>转数组int[][] | ||||||||
2.2 排序
2.3 查找
| 题目 | 难度 | 时间+代码 | 思路 | 知识点 |
|---|---|---|---|---|
| 242. 有效的字母异位词 | 易 | 2020年12月5日 | 哈希映射 | |
| 69. x 的平方根 | 易 | 2020年12月28日 | 二分查找,处理好边界 | |
| 2020年12月29日 | 重做一遍,不用乘法用除法,考虑好边界 | |||
| 2020年12月29日 | 牛顿法 | |||
| 704. 二分查找 | 易 | 2020年10月20日,2020年12月29日 | 经典写法 | |
| 34. 在排序数组中查找元素的第一个和最后一个位置 | 中 | 2021年1月3日 | 二分查找,通过小例子来判断并处理好边界条件 | |
| 81. 搜索旋转排序数组 II | 中 | 2021年1月4日 | 二分查找,判断哪边有序,并处理好特殊情况 | |
| 154. 寻找旋转排序数组中的最小值 II | 难 | 2021年1月5日 | 直接排序 | |
| 2021年1月5日 | 二分法,极简,图解 注意分析题目的特点 | |||
| 540. 有序数组中的单一元素 | 中 | 2021年1月6日 | 方法三:仅对偶数索引进行二分搜索 | 注意数组首位是下标是0,是偶数位 |
2.4 双指针
| 题目 | 难度 | 时间+代码 | 思路 | 知识点 |
|---|---|---|---|---|
| 167. 两数之和 II - 输入有序数组 | 易 | 2020年12月22日 | 双指针 | int[] array = new int[0]; // 定义一个长度为 0 的数组 / 空数组 注意并不是null |
return new int[] {-1, -1}; | ||||
| 88. 合并两个有序数组 | 易 | 2020年12月22日 | 三指针,从后往前,不使用额外空间 | 直接利用数组长度变量作为指针 |
| 142. 环形链表 II | 中 | 2020年12月23日 | 快慢指针原理+图解 | |
| 76. 最小覆盖子串 | 难 | 2020年12月24日 | 滑动窗口 | ASCII表总长128;字符串截取子串s.substring(start, start + min) |
| 633. 平方数之和 | 中 | 2020年12月25日 | 双指针 | 右指针的初始化:int left = 0, right = (int) Math.sqrt(c); |
| 680. 验证回文字符串 Ⅱ | 易 | 2020年12月27日 | java 双指针 附一个自己踩过的坑 | |
| 524. 通过删除字母匹配到字典里最长单词 | 中 | 2020年12月28日 | 双指针、两层for循环 | 初始化 String str = ""; Java compareTo() 方法,字典序(sstr.length() == str.length() && str.compareTo(sstr) > 0) |
