数据结构
-
数组
题目:169. 多数元素
题目:15. 三数之和(难点)
这个方法就是我们常说的「双指针」,当我们需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法。
如果需要和上一次枚举的数不相同,这个技巧在排列组合问题上面也用到了:
if first > 0 and nums[first] == nums[first - 1]: continue
即相同的话就直接判断下一个元素
题目:75. 颜色分类(荷兰国旗问题,经典)
题目:56. 合并区间
题目:706. 设计哈希映射
题目:119. 杨辉三角 II
题目:48. 旋转图像
主对角线翻转+水平翻转,或者,y=x翻转+竖直翻转,答案是前者,代码更简洁
题目:59. 螺旋矩阵 II
题目:435. 无重叠区间
class Solution: def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int: if not intervals: return 0 intervals.sort(key=lambda x: x[1]) n = len(intervals) right = intervals[0][1] ans = 1 for i in range(1, n): if intervals[i][0] >= right: ans += 1 right = intervals[i][1] return n - ans
贪心,按照区间左端点排序,符合要求的添加,则剩余的都是被删除的
左右考虑;贪心,背方法
前缀和+后缀和,智商碾压
-
字符串
题目:415. 字符串相加
题目:409. 最长回文串
题目:290. 单词规律
题目:763. 划分字母区间
题目:49. 字母异位词分组
题目:43. 字符串相乘
题目:5. 最长回文子串
马拉车还是没听懂,去再听一遍左神的,自己写一下代码
-
链表
题目:2. 两数相加
题目:142. 环形链表 II
题目:160. 相交链表(互相指向头节点)
哑节点+快慢指针实现不占用额外空间
题目:707. 设计链表
题目:143. 重排链表(经典题)
-
栈/队列
题目:155. 最小栈
据说有不使用额外空间(辅助栈)的做法
题目:1823. 找出游戏的获胜者(约瑟夫环)
-
树
题目:199. 二叉树的右视图
也可以用dfs
题目:113. 路径总和 II
(非计划)题目:437. 路径总和 III
使用前缀和
题目:450. 删除二叉搜索树中的节点(经典题)
-
图
题目:997. 找到小镇的法官
题目:841. 钥匙和房间
-
优先队列(堆)
算法
-
二分
题目:33. 搜索旋转排序数组(这道题很麻烦,答案的方法很好)
题目:74. 搜索二维矩阵(2次二分更普遍)
题目:162. 寻找峰值(辅助函数处理边界,条件简化)
-
双指针
题解优雅,一次遍历
题目:15. 三数之和
K神的解法更好理解一些,二刷还是不会(OvO)
简单题,但是考察coding能力
题目:986. 区间列表的交集
题目:11. 盛最多水的容器
-
滑动窗口
题目:438. 找到字符串中所有字母异位词(重点)
这道题和之前的一个很像,可以使用diff来记录不同的个数,从而只需要判断进和出的情况
-
dfs/bfs
题目:200. 岛屿数量
题目:547. 省份数量
作为图的dfs/bfs的入门题来看待,是无向无环图
题目:572. 另一棵树的子树(这道简单题不简单)
- dfs:判断路径/结果是否存在
- bfs:寻找最短/最优路径
这里给出一个题解,对dfs和bfs分析的比较好,以及为什么bfs的visited可以全局使用,https://leetcode-cn.com/problems/shortest-path-in-binary-matrix/solution/bfszui-duan-lu-jing-wen-ti-bfsdfsde-si-k-ngc5/
题目:130. 被围绕的区域
逆向思维
题目:797. 所有可能的路径
有向无环图,和上面的一起记忆
-
递归/回溯
题目:78. 子集
题目:90. 子集 II
子集问题:
- 回溯法,增加条件为path的长度,长度满足后就增加一个有效答案,返回
- 二进制掩码
含重复值:排序数组,去重处理(上一个没选择,且当前和上一个相同,则跳过)
(非计划)题目:46. 全排列
题目:47. 全排列 II
排列问题:
- 回溯法,最直接最经典的解法,但是不易处理存在重复元素的情况
- 交换法,以k神为例
含重复值:
- (对于回溯法)排序,同时利用字典和元素判断,这里判断比较复杂不易理解
- (对于交换法)只需要用到字典处理
回溯法:
具体地,我们只要在递归函数中设定一个规则,保证在填每一个空位的时候重复字符只会被填入一次。具体地,我们首先对原字符串排序,保证相同的字符都相邻,在递归函数中,我们限制每次填入的字符一定是这个字符所在重复字符集合中「从左往右第一个未被填入的字符」,即如下的判断条件:
if j in vis or (j-1 not in vis and j > 0 and nums[j] == nums[j-1]): continue
这里还不能直接将元素哈希,只能将元素对应的下标哈希,再进行判断:
class Solution: def permuteUnique(self, nums: List[int]) -> List[List[int]]: def backtrack(i): # 满足条件,这里不能用输入变量了 if len(path) == len(nums): res.append(path[:]) return # 要考虑所有的元素,而不是只考虑当前位置后面的元素,所以用for for j in range(len(nums)): # 上一个选择和本次重复 # 这里为什么是或? # j已经选择过 或者 j-1没选过但是j和j-1对应元素相等 if j in vis or (j-1 not in vis and j > 0 and nums[j] == nums[j-1]): continue vis.add(j) path.append(nums[j]) backtrack(j) path.pop() vis.remove(j) res = [] path = [] vis = set() nums.sort() backtrack(0) return res
交换法:
class Solution: def permuteUnique(self, nums: List[int]) -> List[List[int]]: # 交换法 def backtrack(i): if i == len(nums)-1: res.append(nums[:]) return dct = set() for j in range(i, len(nums)): # 先去重 if nums[j] in dct: continue dct.add(nums[j]) nums[i], nums[j] = nums[j], nums[i] backtrack(i+1) nums[i], nums[j] = nums[j], nums[i] res = [] backtrack(0) return res
交换法只需要进行一次简单的字典判断,有几个区别:
- 字典初始化在回溯中,不是全局的概念;因为只需要判断本次回溯的位置处是否重复
- 字典元素为数组元素,不是下标索引
- 不需要引入额外的path,直接将原数组操作并添加至答案
题目:39. 组合总和
题目:40. 组合总和 II
组合的题感觉更像子集一样,只不过不是全部子集,是有条件的子集
- 当前元素选/不选(适用于可重复使用同一元素),双分支
- 使用for循环验证后面的全部
题目:22. 括号生成(留意一下,回溯条件可以是多个)
题目:79. 单词搜索(经典)
-
动态规划
(非计划)题目:198. 打家劫舍
题目:213. 打家劫舍 II
2种情况下的最大值:如果偷窃了第一间房屋,则不能偷窃最后一间房屋,因此偷窃房屋的范围是第一间房屋到最后第二间房屋;如果偷窃了最后一间房屋,则不能偷窃第一间房屋,因此偷窃房屋的范围是第二间房屋到最后一间房屋。
题目:55. 跳跃游戏
典型的贪心,记住方法;和字节暑期实习笔试题很像(题目就叫“字节跳动”)
题目:45. 跳跃游戏 II(继续Ⅰ的贪心策略)
题目:62. 不同路径
题目:5. 最长回文子串(放在这里有些奇怪,最优解马拉车success)
题目:413. 等差数列划分
和某道题很像,我记得那道题不能只考虑相邻3个元素
题目:91. 解码方法
当前情况等于2种情况相加,但是这2种情况都是要判断才可以
题目:139. 单词拆分
双循环类型dp,第二次循环判断之前某个状态是否满足,即在满足某个小情况(枚举的值那一段在字典中)下,才能求取当前值
题目:300. 最长递增子序列
和上面的题相似,第二次循环中判断每次的情况,即在满足某个小情况(末尾值大于枚举的值)下,才能求取当前值
比较难,在上面的基础上,小循环和大循环都更新数量dp数组
公共子序列问题,必须记忆!
题目:583. 两个字符串的删除操作(问题转化)
题目:72. 编辑距离(困难题,至今不会)
题目:322. 零钱兑换
依旧和
139
、300
一个情况,双循环,内循环的枚举要和外侧枚举值产生关系题目:343. 整数拆分
割绳子问题,dp和贪心都要会
-
位运算
题目:201. 数字范围按位与(最长公共前缀)
-
其他
题目:384. 打乱数组
题目:202. 快乐数
题目:[149. 直线上最多的点数](