题单来源:https://leetcode.cn/studyplan/top-100-liked/
| 类别 | 题目 | 解题思路 |
|---|---|---|
| 哈希表 | 1.两数之和(简单) | |
| 49.字母异位词分组(中等) | ||
| 128.最长连续序列(中等) | ①以每个item为开端且item-1不在set里面,②while循环 +1遍历即可 | |
| 双指针 | 283.移动零(简单) | fast, slow = 0, 0 while fast < n: if nums[fast] != 0: nums[slow], nums[fast] 交换 |
| 26. 删除有序数组中的重复项(简单)(增加) | slow, fast = 1, 1 while fast < n: ifnums[slow - 1] != nums[fast]: nums[slow] = nums[fast] 重写 | |
| 80. 删除有序数组中的重复项 II(中等)(增加) | slow, fast = 2, 2 while fast < n: ifnums[slow - 2] != nums[fast]: | |
| 11.盛最多水的容器(中等) | 1.左右指针从两头往中间靠拢,2.谁小谁先算面积3.然后移动指针 | |
| 15.三数之和(中等) | 1.先排序,2.确定第一个值和第二值,3.第三个值从最后往前找 | |
| 16. 最接近的三数之和(中等)(增加) | 1.先排序,2.前三个最小3.从i开始双指针判断 | |
| 18. 四数之和(中等)(新增) | 1.先排序, | |
| 42.接雨水(困难) | ①从左到右求一个数组,②从右到左求一个数组,③,遍历值累加求和即可 | |
| 407. 接雨水 II (困难)(增加) | ||
| 658. 找到 K 个最接近的元素(中等)(增加) | while right - left + 1 > k: # 缩区间到只剩k个元素 if abs(arr[left] - x) > abs(arr[right] - x): # 左右移动 | |
| 滑动窗口 | 3.无重复字符的最长子串(中等) | ①滑动窗口,每次向右边滑动一下②while循环扩展右边界③更新最长子串;(rk++ )④滑动窗口用set(),删除用remove(元素) |
| 438.找到字符串中所有字母异位词(中等) | winds[ord(s[i]) - ord(‘a’)] -= 1 winds[ord(s[i+len_p]) - ord(‘a’)] += 1 if windp == winds: | |
| 209. 长度最小的子数组(中等)(新增) | 核心思想:①滑动窗口,②要求子序列是连续的,③求和达到一个target的情况下,就开始收缩左边界 | |
| 子串 | 560.和为 K 的子数组(中等) | 前缀和,presum_dict = collections.defaultdict(int)解法:①先累加②求res+=dict[和-k],③字典[和]+=1 |
| 239.滑动窗口最大值(困难) | from collections import deque使用队列 1.while循环删除小个子,2.依次进队列,3.判断窗口是否溢出并q.popleft(),4.从k个位置开始输出 | |
| count = collections.Counter(t) miss = len(t) if miss == 0: # 满足一个窗口时,while循环开始收缩左边界 | ||
| 普通数组 | 53.最大子数组和(中等) | dp[i] = max(dp[i-1]+nums[i], nums[i]) |
| 56.合并区间(中等) | intervals = sorted(intervals,key=lambda x:x[0], reverse=False) | |
| 189.轮转数组(中等) | k = k % n;nums[::] = nums[n-k:] + nums[:n-k] | |
| 238.除了自身以外数组的乘积(中等) | ||
| 41.缺失的第一个正数(困难) | v = nums[i] - 1 if 0 <= v < n and nums[i] != nums[v]: # 交换数据 nums[i], nums[v] = nums[v], nums[i] else:i += 1 # 不符合条件进行+1, | |
| 矩阵 | 73.矩阵置零(中等) | |
| 54.螺旋矩阵(中等) | ||
| 48.旋转图像(中等) | matrix[::] = zip(*matrix[::-1]),1.水平翻转;2.主对角线反转;(如果逆时针则先1.左右翻转;2.主对角线反转;) | |
| 74. 搜索二维矩阵(中等) | 左下角为开始 | |
| 240.搜索二维矩阵 II(中等) | 转化为一维数字 | |
| 链表 | 160.相交链表(简单) | |
| 206.反转链表(简单) | 头插法 | |
| 234.回文链表(简单) | ||
| 141.环形链表(简单) | 同下 | |
| 142.环形链表 II(中等) | 快慢指针, # 解法两阶段,先找入口,在找交点 # 找入口,快慢指针,找交点都是单步 slow, fast = head, head | |
| 287. 寻找重复数(中等)(增加) | 快慢指针, # 解法两阶段,先找入口,在找交点 # 找入口,快慢指针,找交点都是单步 slow = nums[slow];fast = nums[nums[fast]] | |
| 21.合并两个有序链表(简单) | ||
| 2.两数相加(中等) | ||
| 19.删除链表的倒数第 N 个结点(中等) | ||
| 24.两两交换链表中的节点(中等) | ||
| 25.K 个一组翻转链表(困难) | ||
| 138.随机链表的复制(中等) | ||
| 148.排序链表(中等) | ||
| 23.合并 K 个升序链表(困难) | ||
| 146.LRU 缓存(中等) | ||
| 83. 删除排序链表中的重复元素(简单)(增加) | ||
| 82. 删除排序链表中的重复元素 II(中等)(增加) | ||
| 二叉树 | 94.二叉树的中序遍历(简单) | |
| 104.二叉树的最大深度(简单) | ||
| 226.翻转二叉树(简单) | ||
| 101.对称二叉树(简单) | def f(p, q): | |
| 543.二叉树的直径(简单) | self.maxlen = max(self.maxlen, left+right+1) | |
| 102.二叉树的层序遍历(中等) | ||
| 108.将有序数组转换为二叉搜索树(简单) | ||
| 98.验证二叉搜索树(中等) | ||
| 230.二叉搜索树中第 K 小的元素(中等) | ||
| 199.二叉树的右视图(中等) | 队列即可 | |
| 114.二叉树展开为链表(中等) | ||
| 105.从前序与中序遍历序列构造二叉树(中等) | node.left =self.buildTree(preorder[1:idx+1], inorder[:idx]) node.right = self.buildTree(preorder[idx+1:], inorder[idx+1:]) | |
| 106. 从中序与后序遍历序列构造二叉树(中等)(增加) | root.left = self.buildTree(inorder[:idx], postorder[:idx]) root.right = self.buildTree(inorder[idx+1:],postorder[idx:-1]) # [idx:-1] 截止 倒数第二个数 | |
| 112. 路径总和(简单)(增加) | return self.hasPathSum(root.left, targetSum-root.val) or self.hasPathSum(root.right, targetSum-root.val) | |
| 113. 路径总和 II(中等)(增加) | dfs(root.left, targetSum-root.val) dfs(root.right, targetSum-root.val) path.pop() # 回溯法,前一个入坑的需要撤回 | |
| 437.路径总和 III(中等) | sumlist = [v + root.val for v in sumlist] +[root.val],特别注意:①初始化[]②追加的[root.val] return sumlist.count(targetSum) + f(root.right, sumlist) + f(root.left, sumlist) 前缀和:解法:特别注意初始化defaultdict(int)0=1;①先累加②求res+=dict[和-k],③字典[和]+=1,④递归结束后需要字典[和] -= 1 | |
| 236.二叉树的最近公共祖先(中等) | if not root or root == p or root == q: return root # 情况1 找到一个就上报 left = self.lowestCommonAncestor(root.left, p, q) # 情况2 找不到,就左右递归 right = self.lowestCommonAncestor(root.right, p, q) | |
| 124.二叉树中的最大路径和(困难) | left = max(dfs(root.left), 0) # 特别注意 负数的情况 right = max(dfs(root.right), 0) self.maxsum = max(self.maxsum, left+right+root.val)return max(left, right) + root.val | |
| 图论 | 200.岛屿数量(中等) | 找到一个入口,深度优先探查即可 |
| 994.腐烂的橘子(中等) | 队列,先把腐烂的入队,然后出队列,入队,时间+1 | |
| 207.课程表(中等) | 邻接矩阵,判断是否有环 | |
| 261. 以图判树(中等)(增加) | 并查集 | |
| 208.实现 Trie (前缀树)(中等) | ||
| 回溯 | 46.全排列(中等) | 注意用分层的思想方法 |
| 47. 全排列 II(中等)(增加) | if i > 0 and nums[i-1] == nums[i]:continue dfs(nums[:i]+nums[i+1:], path+[nums[i]]) | |
| 78.子集(中等) | res = res + [ v + [item] for v in res] | |
| 90. 子集 II(中等)(增加) | 1.先排序 2.for循环下 : ①去重i > index and nums[i] == nums[i -1] ②dfs(nums, i + 1, path+[nums[i]]) | |
| 17.电话号码的字母组合(中等) | ||
| 39.组合总和(中等) | 可以无限重复取,先排序,分层递归 | |
| 40. 组合总和 II(中等)(增加) | 先排序,判断重复问题 | |
| 22.括号生成(中等) | ||
| 79.单词搜索(中等) | 从每个位置出发,深度优先探索即可 | |
| 131.分割回文串(中等) | 每层“切一点”并验证是否是回文串, | |
| 51.N 皇后(困难) | ||
| 52. N 皇后 II(困难)(增加) | if q[i] == j or abs(q[i]-j) == abs(i-k): # 不同列,不同斜线 | |
| 93. 复原 IP 地址(中等)(增加) | ||
| 二分查找 | 35.搜索插入位置(简单) | 把代码跑起来,就知道res=mid 放到那里了 |
| 74.搜索二维矩阵(中等) | ||
| 34.在排序数组中查找元素的第一个和最后一个位置(中等) | ||
| 33.搜索旋转排序数组(中等) | ||
| 81. 搜索旋转排序数组 II(中等)(增加) | ||
| 153.寻找旋转排序数组中的最小值(中等) | ||
| 154. 寻找旋转排序数组中的最小值 II(困难)(增加) | ||
| 4.寻找两个正序数组的中位数(困难) | ||
| 378. 有序矩阵中第 K 小的元素(中等)(增加) | 1.核心思想:值域二分法2. total += bisect.bisect_right(row, x) | |
| 410. 分割数组的最大值(困难)(增加) | 1.核心思想:值域二分法left, right = max(nums), sum(nums) # 确定上下界 | |
| 658. 找到 K 个最接近的元素(中等)(增加) | ||
| 162. 寻找峰值(中等)(增加) | if nums[mid] > nums[mid + 1]:,特别注意# 大于右边 | |
| 栈 | 20.有效的括号(简单) | |
| 155.最小栈(中等) | ||
| 394.字符串解码(中等) | # 核心思想: 1.遇到左号,进栈,2.遇到右号,出栈 3.遇到数字,积攒 4.字符串,就拼接 | |
| 726. 原子的数量(困难)(增加) | ||
| 739.每日温度(中等) | # 核心思路:①while踢出小个子+的并登记,②进栈 | |
| 84.柱状图中最大的矩形(困难) | # 核心思想:①while踢出高个子,并计算一次面积,特别注意:stack =[-1], 尾巴append(0) | |
| 85. 最大矩形(困难)(增加) | # 核心思想,踢出高个子,并计算一次面积,特别注意:stack =[-1] | |
| 32.最长有效括号(困难)(增加) | 特别注意:stack =[-1] | |
| 堆 | 215.数组中的第K个最大元素(中等) | |
| 347.前 K 个高频元素(中等) | ||
| 295.数据流的中位数(困难) | ||
| 贪心算法 | 121.买卖股票的最佳时机(简单) | 记录的是最小值 |
| 55.跳跃游戏(中等) | ||
| 45.跳跃游戏 II(中等) | 核心 :if next_max >= index: next_max = max(next_max, item+index) | |
| 763.划分字母区间(中等) | ||
| 135. 分发糖果(困难)(增加) | ||
| 动态规划 | 122. 买卖股票的最佳时机 II(中等)(增加) | 可以买卖多次,求梯度和即可 |
| 123. 买卖股票的最佳时机 III(困难) | hold = [float(‘-inf’)] * (k+1) # 持有股票时的状态 - 剩余的钱或者手里的钱 sold = [0] * (k+1) # 已经销售时的状态 - 剩余的钱或者手里的钱 | |
| 188. 买卖股票的最佳时机 IV(困难)(增加) | hold[j] = max(hold[j], sold[j-1] - price) sold[j] = max(sold[j], hold[j] + price) hold[j] # 物理含义,当前你持有股票的时,你有多少钱?显然上一个状态不持有股票买入就减去 sold[j] # 物理含义,当你不持有股票的时,你有多少钱?显然上一个持有股票卖出去,就是加上 | |
| 312. 戳气球(困难)(增加) | dp = [[0] * n for _ in range(n)] # 初始化dp (头尾+[1],把0都删除)dp[left][right] = max(dp[left][right], nums[left] * nums[i] * nums[right] + dp[left][i] + dp[i][right]) | |
| 887. 鸡蛋掉落(困难)(增加) | 1.dp[m][k] =拥有k个鸡蛋,最多允许尝试m次操作,最坏情况下,能够保证测出临界点的最大楼层数量。鸡蛋碎了: dp[m - 1][k - 1],鸡蛋没碎:dp[m-1][k],当前层:+1dp[m][k] = dp[m - 1][k - 1] + dp[m - 1][k] + 1 | |
| 1000. 合并石头的最低成本(困难)(增加) | ||
| 70.爬楼梯(简单) | ||
| 118.杨辉三角(简单) | row.append(res[i-1][j] + res[i-1][j-1]) | |
| 198.打家劫舍(中等) | dp[i] = max(dp[i-2] + nums[i], dp[i-1]) | |
| 213. 打家劫舍 II(中等)(增加) | ||
| 279.完全平方数(中等) | 对于每个 i(从 1 到 n),遍历所有小于等于 i 的完全平方数 j², 则 f[i] = min(f[i - j²]) + 1(+1 表示加上当前的 j² 这个数) for i in range(1, n + 1): for j in range(1, int(i ** 0.5) + 1): dp[i] = min(dp[i], dp[i - j * j] + 1) | |
| 322.零钱兑换(中等) | 核心思想:可以理解为爬楼梯题目,有多少个路径可以通向终点,上一个状态是什么?if i - coin >= 0: dp[i] = min(dp[i], dp[i-coin] + 1) | |
| 518. 零钱兑换 II(中等)(增加) | for coin in coins for i in range(amount+1): if i - coin >=0:dp[i] += dp[i-coin] | |
| 139.单词拆分(中等) | if dp[j] and s[j:i] in wordDict: dp[i] = True | |
| 300.最长递增子序列(中等) | if nums[i] > nums[j]: dp[i] = max(dp[i], dp[j]+1) # 特别注意 判断条件 | |
| 152.乘积最大子数组(中等) | dpmax[i] = max(nums[i], nums[i]*dpmin[i-1], nums[i]*dpmax[i-1]) dpmin[i] = min(nums[i], nums[i]*dpmin[i-1], nums[i]*dpmax[i-1]) | |
| 416.分割等和子集(中等) | for num in nums: # 遍历每个数字,每个数只能选一次 for j in range(target, num - 1, -1): # 倒序遍历,防止重复选取同一数字 dp[j] = dp[j] or dp[j - num] # 不选当前数 / 选当前数,满足其一即可 | |
| 32.最长有效括号(困难) | ||
| 多维动态规划 | 62.不同路径(中等) | |
| 64.最小路径和(中等) | ||
| 5.最长回文子串(中等) | ||
| 718. 最长重复子数组(中等)(增加) | if A[i-1] == B[j-1]: dp[i][j] = dp[i-1][j-1] + 1 | |
| 1143.最长公共子序列(中等) | # dp[i][j] = text1[i]== text2[j] --> dp[i-1][j-1] + 1 # 不相等时,dp[i][j] = max(dp[i-1][j], dp[i][j-1]) | |
| 72.编辑距离(中等) | if word1[i-1] == word2[j-1]: dp[i][j] = dp[i-1][j-1] else: dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1 | |
| 技巧 | 136.只出现一次的数字(简单) | return reduce(lambda x,y:x^y, nums) |
| 169.多数元素(简单) | ||
| 75.颜色分类(中等) | ||
| 31.下一个排列(中等) | 画图理解即可 | |
| 287.寻找重复数(中等) | 快慢双指针找环 | |
| 其他 | 263. 丑数(简单) | for p in [2, 3, 5]: while num % p == 0 and num > 0: num = num // p |
| 264. 丑数 II(中等) | while ugly[i2] * 2 <= ugly[-1] |