(LeetCode)刷题记录

382 阅读12分钟

0. 方法

大家都是如何刷 LeetCode 的? - 知乎

  • 按从低到高的难度分组刷
  • 按 tag 分类刷
  • 定期复习,重做之前刷过的题

动画图解 - LeetCodeAnimation

  • 可以看一看

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. 下一个更大元素 I2020年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. 二叉树的层次遍历 II2020年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 位、有符号的以二进制补码表示的整数;
intfloat 是32位
653. 两数之和 IV - 输入 BST2020年11月25日使用 HashSetHashSet 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. 从上到下打印二叉树 II2020年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. BiNode2020年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. 买卖股票的最佳时机 II2020年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. 无重叠区间的基础上修改image-20201219212323929
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 == 0flowerbed[i - 1] == 0) && (i == flowerbed.length - 1flowerbed[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 排序

题目难度时间+代码思路知识点
912. 排序数组2020年10月30日写了个快排?
242. 有效的字母异位词2020年12月5日转化为char[],调用Arrays的方法sortequals
350. 两个数组的交集 II2020年12月6日哈希表
2020年12月6日排序 + 双指针Arrays.copyOfRange(int [] original, int from, int to)
922. 按奇偶排序数组 II2020年12月6日方法3:原地交换
976. 三角形的最大周长2020年12月8日贪心 + 排序小白带你学---贪心算法(Greedy Algorithm) - 小白算法的文章 - 知乎
1030. 距离顺序排列矩阵单元格2020年12月8日桶排序(含复杂度分析)详细一点的解法说明快速入门桶排序 - NuoHui的文章 - 知乎三分钟搞懂桶排序
1122. 数组的相对排序2020年12月9日计数排序注意处理好边界
1356. 根据数字二进制下 1 的数目排序2020年12月10日循环并使用 Integer.bitCount 计算数字中1的个数,乘以10000000(题目中不会大于 10^4)然后加上原数字,放入数组 map 中,并对 map进行排序,最后 % 10000000 获取原来的数组,填充到原数组返回即可① 法1:Integer.bitCount(x) 可以统计x用二进制表示时1的个数 ② 法2:(笔记)Java统计二进制数中1的个数
低位存原数值,高位存1的个数,就可以直接排序了
1370. 上升下降字符串2020年12月10日① Count the frequency of each character.可以不转化char[] charArray = s.toCharArray(); 直接遍历s。但转化为数组速度似乎更快
桶排序② Loop over all character from 'a' to 'z' and append the character if it exists and decrease frequency by 1. Do the same from 'z' to 'a'.强制转型:stringBuilder.append((char) ('a' + i));
③ Keep repeating until the frequency of all characters is zero.循环的终止条件:int size = s.length(); 然后判断新的字符串的长度是否已经达到size
1403. 非递增顺序的最小子序列2020年12月11日直接排序JAVA使用Arrays.sort()升序和降序
int[] 无法强制转型为 Integer[]
1491. 去掉最低工资和最高工资后的工资平均值2020年12月11日直接排序
1502. 判断能否形成等差数列2020年12月11日直接排序
1528. 重新排列字符串2020年12月11日不用排序return new String(chars); // chars是char[] 参考Java中char和String的转换
1636. 按照频率将数组升序排序2020年12月11日高位存频率,低位存数值
1640. 能否连接形成数组2020年12月13日1. 将每个 piece 的第一个整数作为 key 存到 map 中;2. 检查 arr 中每个元素,如果在 map 中找到,再接着判断 piece 后面的整数
215. 数组中的第K个最大元素2021年1月7日堆排序;直接调用快排
2021年1月14日快速选择(自己写的不够快呀)快速排序的退化版本
347. 前 K 个高频元素2021年1月17日哈希表+桶排序注意new List[] 是没有<>的;
if(buckets[i] == null) buckets[i] = new ArrayList(); 需要调用构造函数初始化

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. 搜索旋转排序数组 II2021年1月4日二分查找,判断哪边有序,并处理好特殊情况
154. 寻找旋转排序数组中的最小值 II2021年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. 环形链表 II2020年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)