LeetCode 刷题总结
This repository is to record some leetcode's study experience.
一、 总结
二、刷题记录
序号 | 题目序号 | 题目解法 | 复杂度 |
---|---|---|---|
1 | 1. 两数之和 | 哈希表 | 时/空 - O(n) / O(n) |
2 | 10. 正则表达式匹配 '.' 和 '*' | 动态规划 | 时/空 - O(mn) / O(mn) |
3 | 100. 相同的树 | 深度优先 广度优先 |
时/空 - O(n) / O(min(m,n)) 时/空 - O(n) / O(min(m,n)) |
4 | 1011. 在D天内送达包裹的能力 | 左右指针二分查找 | 时/空 - O(NlogN) / O(1) |
5 | 111. 二叉树的最小深度 | 递归深度/广度优先 | 时/空 - O(n) / O(log(n)) |
6 | 1118. 一月有多少天 | 闰年判断:能400整除,能4但不能100整除 | 无 |
7 | 1143. 最长公共子序列 | 动态规划 | 时/空 - O(mn) |
8 | 130. 被围绕的区域 | 递归深度 并查集 |
时/空 - O(n) / O(1) 时/空 - O(n) / O(n) |
9 | 141. 环形链表 | 哈希表 快慢指针 |
时/空 - O(n) 时/空 - O(n) / O(1) |
10 | 142. 环形链表II | 哈希表 快慢指针 |
时/空 - O(n) 时/空 - O(n) / O(1) |
11 | 146. LRU缓存机制 | 双向哈希链表(get / put) | 操作 - O(1) |
12 | 167. 两数之和 II - 输入有序数组 | 左右指针两边夹 二分查找 |
时/空 - O(N) / O(1) 时/空 - O(NlogN) / O(1) |
13 | 170. 两数之和 III - 数据结构设计 | 哈希表法 左右指针两边夹 |
时间 add【O(1)】 find【O(n)】 空间 - O(n) |
170. 两数之和 III - 数据结构设计 | 左右指针二分查找 | 时间 add【O(1)】 find【O(n log(n))】 空间 - O(n) |
|
14 | 198. 打家劫舍 | 动态规划 滚动窗口 |
时/空 - O(n) / O(n) 时/空 - O(n) / O(1) |
15 | 20. 有效的括号 | 暴力循环 | 时/空 - O(n) |
16 | 204. 计数质数 | 暴力求解 高效算法 - Sieve of Eratosthenes |
时/空 - O(n^2) / O(1) 时/空 - O(N*logN)/ O(1) |
17 | 213. 打家劫舍II | 动态规划 | 时/空 - O(n) |
18 | 22. 括号生成 | 递归深度/广度优先 回溯算法 动态规划 |
时/空 - O(n^2) |
19 | 222. 完全二叉树的节点个数 | 暴力递归 递归算出深度,二分查找看节点是否存在 |
时/空 - O(n) / O(logn) 时/空 - O(log2n) / O(1) |
20 | 224. 基本计算器 | 栈和反转字符串 通用解法 |
时/空 - O(n) 时/空 - O(n) |
21 | 225. 用队列实现栈 | 单队列 Queue、Deque【LinkedList】 双队列 Queue【ArrayDeque】 |
时/空 - |
22 | 227. 基本计算器II | 通用解法 | 时/空 - O(n) 时/空 - O(n) |
23 | 232. 用栈实现队列 | 双栈模拟 | |
24 | 234. 回文链表 | 将值复制到数组中后用双指针法 反转后半部分链表 |
时/空 - O(n) / O(n) 时/空 - O(n) / O(1) |
25 | 236. 二叉树的最近公共祖先 | 递归深度优先 | 时/空 - O(n) / O(log n) |
26 | 239. 滑动窗口最大值 | 双端队列 + 单调队列 + 滑动窗口 | 时/空 - O(n) / O(n) |
27 | 25. K个一组翻转链表 | 翻转部分链表 | 时/空 - O(n) |
28 | 26. 删除排序数组中的重复项 | 暴力修改 | |
29 | 28. 实现 strStr() | 暴力求解 | 时/空 - O(mn) |
30 | 292. Nim游戏 | 不能被4整除 | |
31 | 3. 无重复字符的最长子串 | 哈希表 | 时/空 - O(n) |
32 | 300. 最长上升子序列 | 动态规划 二分查找 |
时/空 - O(n^2) / O(n) 时/空 - O(N·logN) / O(n) |
33 | 312. 戳气球 | 记忆化搜索 动态规划 |
时/空 - O(n^3) / O(n^2) 时/空 - O(n^3) / O(n^2) |
34 | 319. 灯泡开关 | 1. 亮与否,跟操作次数有关 2. 操作次数就是该数的因数个数 3. 因数为奇数则亮灯 4. 奇数表明该位置是完全平方数 5. 计算有多少个完全平方数 |
|
35 | 322. 零钱兑换 - 最少的硬币个数 | 动态规划 | 时/空 - O(mn) / O(n) |
36 | 337. 打家劫舍III | 递归深度优先 | 时/空 - O(n) / O(logn) |
37 | 34. 在排序数组中查找元素的第一个和最后一个位置 | 暴力左右指针两边夹 二分搜索 - 寻找左侧边界 二分搜索 - 寻找右侧边界 |
时/空 - O(n) |
38 | 354. 俄罗斯套娃信封问题 | 1. 对宽度 w 进行升序排序 2. 对相同w的 高度 h 降序排序 3. 最长上升子序列求解 |
时/空 - O(n^2) / O(n) |
39 | 355. 设计推特 | 1. 哈希表来存储用户的信息 2. 链表存储发送的推文 3. 优先队列(大顶堆)排序 |
|
40 | 37. 解数独 | 回溯算法 | |
41 | 372. 超级次方 | 1. a[1,2,3,4] = (a[1,2,3]) ^ 10 · a ^ 4 2. (a * b) % p = (a % p * b % p) % p |
|
42 | 382. 链表随机节点 | 1. Random.nextInt - 【0, n) 2. 以 1/i 的概率选择第i个元素 |
|
43 | 384. 打乱数组 | 1. 以 1/i 的概率选择第i个元素 2. Fisher-Yates 洗牌算法 |
|
44 | 392. 判断子序列 | 双指针 | 时/空 - O(n+m) / O(1) |
45 | 398. 随机数索引 | 以 1/i 的概率选择第i个元素 | |
46 | 416. 分割等和子集 | 1. 0-1背包问题 + 动态规划 2. 0-1背包问题 + 动态规划 + 滚动数组 |
时/空 - O(nc) / O(nc) 时/空 - O(nc) / O(c) |
47 | 42. 接雨水 | 按列求解 | 时/空 - O(n) / O(n) |
48 | 43. 字符串相乘 | 优化竖式,用一维数组存储结果集每一位 | 时/空 - O(mn) / O(m+n) |
49 | 435. 无重叠区间 | 1. 先以end做升序排序 2. 贪心解法 |
时/空 - O(n) / O(1) |
50 | 438. 找到字符串中所有字母异位词 | 滑动窗口 | 时/空 - O(mn) / O(1) |
51 | 448. 找到所有数组中消失的数字 | 1. 哈希表 2. 原地修改【数值取负数】 |
时/空 - O(n) / O(n) 时/空 - O(n) / O(1) |
52 | 45. 跳跃游戏 II | 贪心算法 | 时/空 - O(n) / O(1) |
53 | 450. 删除二叉搜索树中的节点 | 1. 二叉排序树 - 中序 - 升序结果 2. 前驱节点 3. 后继节点 4. 递归深度优先 |
|
54 | 452. 用最少数量的箭引爆气球 | 1. 先以end做升序排序 2. 贪心解法 |
时/空 - O(NlogN) / O(1) |
55 | 46. 全排列 | 回溯算法 + 深度优先 | |
56 | 496. 下一个更大元素I - 非循环数组 | 1. 双指针 2. 单调栈 |
时/空 - O(N^2 + M) / O(N) 时/空 - O(N + M) / O(N) |
57 | 5. 最长回文子串 | 1. 暴力解法+双指针两边夹 2. 动态规划 |
时/空 - O(n^3) / O(1) 时/空 - O(n^2) / O(n^2) |
58 | 503. 下一个更大元素II - 循环数组 | 1. 双倍数组,逆序遍历,push前赋值 2. 单调栈 |
时/空 - O(n) / O(n) |
59 | 509. 斐波那契数 | 动态规划 | 时/空 - O(n) / O(n) |
60 | 51. N皇后 | 回溯算法 | 时/空 - O(n!) / O(n) |
52. N皇后 II | 回溯算法 | 时/空 - O(n!) / O(n) | |
61 | 516. 最长回文子序列 | 动态规划 | 时/空 - O(n^2) / O(n^2) |
62 | 518. 零钱兑换 II - 硬币组合数 | 动态规划 + 完全背包问题 + 分类计数原理 | 时/空 - O(m · n^2) / O(m · n) 时/空 - O(n^2) / O(n) |
63 | 53. 最大子序和 | 双层循环 | 时/空 - O(n!) / O(1) |
64 | 55. 跳跃游戏 | 贪心算法 回溯算法 |
时/空 - O(n) / O(1) 时/空 - O(n!) / O(1) |
65 | 56. 合并区间 | 排序 + 大小值指针 | 时/空 - O(nlogn) / O(n) |
66 | 560. 和为K的子数组 | 枚举法 前缀和 + 哈希表优化 |
时/空 - O(n^2) / O(1) 时/空 - O(n) / O(n) |
67 | 567. 字符串的排列 | 哈希表法 + 滑动窗口 数组法 + 滑动窗口 |
时/空 - O(mn) / O(1) |
68 | 645. 错误的集合 | 排序法 哈希表法 额外数组法 额外空间法 |
时/空 - O(n · log n) / O(1) 时/空 - O(n) / O(n) 时/空 - O(n) / O(n) 时/空 - O(n) / O(1) |
69 | 651. 四键键盘 | ||
70 | 700. 二叉搜索树中的搜索 | 深度优先遍历 | 时/空 - O(n) / O(1) |
71 | 701. 二叉搜索树中的插入操作 | 深度优先遍历 | 时/空 - O(n) / O(1) |
72 | 704. 二分查找 | 二分查找 | 时/空 - O(n) / O(1) |
73 | 72. 编辑距离 | 动态规划 | 时/空 - O(mn) / O(mn) |
74 | 733. 图像渲染 | 深度优先遍历 | 时/空 - O(n) / O(1) |
75 | 752. 打开转盘锁 | 广度优先遍历 | 时/空 - O(N^2 · A^N + D) / O(A^N + D) A 表示数字的个数, N 表示状态的位数, D 表示死亡数字数组的大小 |
76 | 76. 最小覆盖子串 | 滑动窗口 | 时/空 - O(m + n) / O(m + n) |
77 | 77. 组合 | 回溯算法 | 时/空 - O(n * k) / O(n) |
78 | 772. 基本计算器III | 通用解法 | 时/空 - O(n) 时/空 - O(n) |
79 | 773. 滑动谜题 | 广度优先遍历 | 时/空 - O(N^2 · A^N + D) / O(A^N + D) A 表示数字的个数, N 表示状态的位数 |
80 | 78. 子集 | 回溯算法 | 时/空 - O(n!) / O(n) |
81 | 83. 删除排序链表中的重复元素 | 哈希表法 | 时/空 - O(n) / O(n) |
82 | 855. 考场就座 | 使用 TreeSet | 时/空 - O(P) / O(n) seat() : 遍历整个有序集合 - O(P) leave() : 遍历树高 - O(logP) |
83 | 875. 爱吃香蕉的珂珂 | 二分查找 | 时/空 - O(NlogN) / O(1) |
84 | 877. 石子游戏 | 数学方式 动态规划 记忆化递归 + 相对分数 |
时/空 - O(1) / O(1) 时/空 - O(n ^ 2) / O(n ^ 2) 时/空 - O(NlogN) / O(1) |
85 | 887. 鸡蛋掉落 | 递归 + 备忘录 + 二分法 动态规划 - 二分法求解 |
时/空 - O(n * k · log n) / O(n * k) 时/空 - O(n * k · log n) / O(n * k) |
86 | 92. 反转链表 II | 翻转链表 | 时/空 - O(n) / O(1) |
87 | 969. 煎饼排序 | 查找最大的下标,放到数组末尾,递归从后向前 | 时/空 - O(n^2) / O(1) |
88 | 98. 验证二叉搜索树 | 深度优先递归遍历 中序遍历 |
时/空 - O(nlog n) / O(1) |
89 | 986. 区间列表的交集 | 大小值指针遍历 | 时/空 - O(m + n) / O(1) |
90 | 990. 等式方程的可满足性 | 并查集 | 时/空 - O(n) / O(n) |
91 | 121. 买卖股票的最佳时机 | ||
92 | 122. 买卖股票的最佳时机 II | ||
93 | 123. 买卖股票的最佳时机 III | ||
94 | 188. 买卖股票的最佳时机 IV | ||
95 | 309. 最佳买卖股票时机含冷冻期 | ||
96 | 714. 买卖股票的最佳时机含手续费 |
序号 | 题目序号 | 题目解法 | 复杂度 |
---|---|---|---|
97 | 2. 两数相加 | 暴力求解 | 时/空 - O(m+n) / O(1) |
98 | 4. 寻找两个正序数组的中位数 | 归并排序 二分法查找 - 递归 |
时/空 - O(m+n) / O(m+n) 时/空 - O(log(m+n)) / O(1) |
99 | 6. Z 字形变换 | 暴力Flag求解 | 时/空 - O(n) / O(n) |
100 | 7. 整数反转 | 按位反转,注意数据溢出 | 时/空 - O(n) / O(1) |
101 | 8. 字符串转换整数 (atoi) | 暴力解法,注意数据溢出 | 时/空 - O(n) / O(1) |
102 | 9. 回文数 | 暴力解法,左右指针两边夹,注意抹掉高位和地位的方式 | 时/空 - O(n) / O(1) |
103 | 11. 盛最多水的容器 | 暴力解法,左右指针两边夹 | 时/空 - O(n) / O(1) |
104 | 14. 最长公共前缀 | 暴力解法 | 时/空 - O(n) / O(1) |
105 | 15. 三数之和 | 哈希表 排序后,双指针两边夹 |
时/空 - O(n^2) / O(n) 时/空 - O(n^2) / O(1) |
106 | 16. 最接近的三数之和 | 排序后,双指针两边夹 | 时/空 - O(n^2) / O(1) |
107 | 17. 电话号码的字母组合 | 广度优先遍历 回溯算法 |
|
108 | 18. 四数之和 | 排序后,左右指针两边夹 | 时/空 - O(n^3) / O(1) |
109 | 19. 删除链表的倒数第N个节点 | 快慢指针 | 时/空 - O(n) / O(1) |
110 | 21. 合并两个有序链表 | 归并排序 递归求解 |
时/空 - O(m+n) / O(m+n) 时/空 - O(m+n) / O(1) |
111 | 23. 合并K个升序链表 | 分治-链表两两合并 优先级队列 |
时/空 - O(m+n) / O(m+n) 时/空 - O(nlogk) / O(1) |
112 | 24. 两两交换链表中的节点 | 非递归解法 递归解法 |
时/空 - O(n) / O(1) 时/空 - O(n) / O(1) |
113 | 27. 移除元素 | 拷贝覆盖 | 时/空 - O(n) / O(1) |
114 | 29. 两数相除 | 负数累加计数,排除正数溢出问题 | |
115 | 30. 串联所有单词的子串 | 哈希表 | 时/空 - O(mn) / O(mn) |
116 | 39. 组合总和 | 回溯算法 | |
117 | 40. 组合总和 II | 回溯算法 | |
118 | 47. 全排列 II | 回溯算法,Deque(LinkedList)优化存取 | |
119 | 62. 不同路径 | 动态规划 | 时/空 - O(n^2) / O(n^2) |
120 | 63. 不同路径 II | 动态规划,翻转二维数组,尾部开始遍历 | 时/空 - O(n^2) / O(n^2) |
121 | 69. x 的平方根 | 二分搜索法 牛顿迭代法 |
时/空 - O(log n) / O(1) |
122 | 70. 爬楼梯 | 递归斐波那契数列方法(带缓存) 动态规划 |
时/空 - O(n) / O(n) 时/空 - O(n) / O(n) |
123 | 90. 子集 II | 回溯算法 | |
124 | 102. 二叉树的层序遍历 | 深度优先 广度优先 |
时/空 - O(n) / O(logn) 时/空 - O(n) / O(logn) |
125 | 120. 三角形最小路径和 | 深度优先 动态规划 |
时/空 - O(2^(m*n)) / O(log n) 时/空 - O(mn) / O(n) |
126 | 152. 乘积最大子数组 | 用零分割多段数组,每段数组通过负数个数求相乘最大值 动态规划 |
时/空 - O(n) / O(n) 时/空 - O(n) / O(1) |
127 | 169. 多数元素 | 暴力求解 哈希表 先排序,后遍历,大于 n/2即可 分治求解 |
时/空 - O(n^2) / O(n) 时/空 - O(n) / O(n) 时/空 - O(nlog) / O(1) 时/空 - O(n) / O(n) |
128 | 200. 岛屿数量 | 染色法(广度优先) 染色法(深度优先) 并查集 |
时/空 - O(n^2) / O(n) 时/空 - O(n^2) / O(1) 时/空 - O(n^2) / O(n) |
129 | 206. 反转链表 - (单链表 / 双向链表) | 一次遍历,存储"前一个、下一个(+临时)节点" | 时/空 - O(n) / O(1) |
130 | 208. 实现 Trie (前缀树 / 字典树) | 字典树,用n叉树实现 注意:从A开始到z一共58个字符(26 * 2 + 6) |
时/空 - O(n) / O(1) |
131 | 212. 单词搜索 II | 字典树 + 回溯算法 | 时/空 - O(n^n + m) / O(mn) |
132 | 242. 有效的字母异位词 | 遍历一维数组 | 时/空 - O(n) / O(1) |
133 | 338. 比特位计数 | i & (i - 1) 可以去除二进制数中最小的1 | 时/空 - O(n) / O(1) |
134 | 547. 朋友圈 | 并查集 | 时/空 - O(n^2) / O(n) |
135 | 703. 数据流中的第 K 大元素 | 堆排序 | 时/空 - O(log n) / O(1) |
136 | 144. 二叉树的前序遍历 | 深度优先遍历 | 时/空 - O(log n) / O(1) |