算法思路
- 先判断边界条件,尤其注意 int 类型边界问题。
- 数据如果元素顺序对结果没有影响的话尝试先进行排序。
- 数组遍历的时候试一下倒序遍历,看是否比正序更好处理。
- 数组双层循环遍历使用双指针优化,双指针还可以尝试下同向、逆向、相向是否可行。
- 如果无思路就先想出暴力解法,再根据暴力解法进行优化。
- 递归尝试优化为迭代,使用循环处理。
- 链表操作尝试添加虚拟头结点可避免维护头结点的麻烦。
- Map 操作如果数据范围不大的话尝试改为数组,比如 26 个英文字母这样。
-
在使用异或操作交换数组元素时,会遇到传入两个下标相同的情况,这时异或操作实际上变成了
a^=a;a^=a;a^=a
;这时 a 的值会变成 0。解决方法:public static void swap(int[] arr,int i,int j){ if(i==j) return; a[i]^=a[j]; a[j]^=a[i]; a[i]^=a[j]; }
- 二叉树递归函数究竟什么时候需要返回值,什么时候不要返回值。
搜索一条边的写法:
if (递归函数(root->left)) return ; if (递归函数(root->right)) return ;
搜索整个树写法:
left = 递归函数(root->left); // 左 right = 递归函数(root->right); // 右 left 与 right的逻辑处理; // 中
在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。
- 回溯算法数组先排序,注意剪枝,可以从元素数量和目标和两个维度进行剪枝。
- 如果把子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点。
- 回溯树层去重和树枝去重,数层去重不回溯。 491. 递增子序列
- 01背包压缩为一维数组的时候要倒序遍历背包。
-
完全背包 如果求组合数就是外层for循环遍历物品,内层for遍历背包。如果求排列数就是外层for遍历背包,内层for循环遍历物品。
- 动态规划的如果无思路就先定义
dp
数组表示以某个字符为结尾的目标值。