一、链表
如果遇到需要删除头节点的题目,添加哨兵节点可以简化代码逻辑,请记住这个技巧。 –灵神
- 头节点会被删除的话,需要建立dummyNode
- 反转链表有个很重要的性质:pre指向反转后这一段的末尾,cur指向这一段的下一个节点
二、双指针
- 三数之和:如果数组有序,可以使用双向双指针
三、字符串、字符映射技巧
- 代码实现时,可以创建一个哈希表(或者数组),把字符作为 key,对应的数值作为 value,从而避免写一堆if-else。
- 代码实现时,由于 T 和 F 的 ASCII 值除以 2 后的奇偶性不同,也就是它们二进制的次低位不同,可以改为统计二进制次低位。
- 如果字符串只包含小写字母或者大写字母,即只有26个,可以用[26]int{}数组代替map; 如果只包含空格、字符、数字(ASCII都是在128之内的),可以用[128]int{}代替map
- 对于二进制,做法类似,往110的右边添加1,得到1101,做法是
110*2+1=1101,或者110<<1 ∣ 1=1101。 - 异或就象消消乐,2个相同就消除了。
统一从0开始
1 | 字符->数字 c-‘a’ |
四、数组
子数组问题:没有负数 同向滑动 考虑滑动窗口; 有负数 前缀和
循环数组:(negidx-i + n) % n 向左取数,防止越界; (negidx+i)%n 向右取数 ;保证下标是在0-n-1之间
负数 (I%n +n) % n ; 正数: (I%n) % n
五、回溯分类
- 子集型回溯(0-1背包属于子集型)
- 子序列本质是数组的子集,可以使用子集型回溯思考:选或不选(相邻不相关);枚举选哪个(相邻相关)
- 组合型
- 排列型
六、递归->记忆化搜索->动态规划
子问题和原问题是相似的,这种从原问题到子问题的过程,适合用递归解决。
递归:怎么往上「递」,怎么往下「归」
参数定义
ijk的状态分别可以表示遍历到不同的阶段,如i,j某个坐标,k是另一个子串的下标,如lc单词搜索:
枚举 i=0,1,2,…,m−1 和 j=0,1,2,…,n−1,以 (i,j) 为起点开始搜索。
同时,我们还需要知道当前匹配到了 word 的第几个字母,所以还需要一个参数 k。
递归->记忆化搜索 ->1:1改 递推。 递推初始值可以参考递归出口,递归改循环
01背包:不能重复选 dfs(i-1,c)+dfs(i-1,c-nums[i])
完全背包:可以重复选dfs(i-1,c)+dfs(i-,c-nums[i])
go 两种深拷贝写法:
1
2ans = append(ans, slices.Clone(path)) // 复制 path
ans = append(ans, append([]int(nil), path...))
数论 & 图
- 除了2以外其他质数都是奇数
- 任意两个点的最短路:floyd ; 一个起点的最短路:dijstra
数学公式
向上取整:a b均为整数, 有恒等式:
$$
\left\lceil \frac{a}{b} \right\rceil
= \left\lfloor \frac{a + b - 1}{b} \right\rfloor
= \left\lfloor \frac{a - 1}{b} \right\rfloor + 1
$$
$\left\lceil \frac{a}{b} \right\rceil
= \left\lfloor \frac{a + b - 1}{b} \right\rfloor
= \left\lfloor \frac{a - 1}{b} \right\rfloor + 1$