- 处理有序数组时,先考虑双指针(对撞指针,快慢指针)。
- 形参引用类型,先考虑形参是否为 null 吧。
- 接2,迭代链表时,不要随便就 cur.next.next,你考虑过 cur.next 是null吗?
- 接3,如果不想考虑 null,可以试着新维护两个头、尾结点(dummyHead,dummyTail)。
- 能用 for 别用 while。
- 接5,头铁非要用 while,别在循环判定条件里更新控制变量!!!
- 不简洁但一眼就能看明白的代码,要优于那些形式上简洁但不直观的(不要为了简洁优雅而耗费时间,有那功夫想想性能咋提高吧)。
- 链表结构可以使用“依序交织”的手法“建立映射关系”,起到hashSet的效果。
- 递归有“top-down”与“bottom-up”两种方式,前者层序递归至底层即可得出结果;后者要将底层的结果再传播给最顶结点。
- 分治与递归很相似,区别是,前者将当前问题分成两个以上的子问题,结合所有子问题的结果解决当前问题;而后者是将当前问题变成一个更小的子问题,通过子问题的结果可以递推出当前问题的结果。
- 快排,双指针重合处恰为基准正确位置的原因:考虑最后一次有效赋值操作,无论是将low赋给high或是反之,由于是最后一次有效赋值,因此赋值后,赋值指针指向的位置刚好就是基准的正确位置,而下一步必是被赋值指针向赋值指针会合,因此双指针会合处永为基准正确位置。
- 快排的优势在于,一次快排后,某元素会在正确的位置,即,该元素左边的数都小于它,右边的值都大于它,即,该元素将搜索区间二分了(不考虑该元素恰为边界元素的恶劣情况)。可以利用此信息,决定下一次的搜索区间。
- 接上一条,二分搜索(或二分查找)也并不一定要求数据有序,只要在搜索区间二分后,能够决定下一步的搜索区间是左还是右即可。
- 递归可以不断深入,但当每步的可行解不止一种时,需要遍历当前所有可行解,也就是,在一条路(递归)走到头(剪枝,早停)后,要返回来(回溯)再试试另一条路。(入栈出栈、链表、二叉树)。
- 滑动窗口法的本质是剪枝。剪枝即缩小解空间,要想如此,必须引入其他约束条件,合理利用信息。
- 队列实现二叉树层序遍历,可以维护一个 tail 结点指示当前层,但更简单的做法是,获取当前队列内元素数,循环遍历,再进行下一层。如果只要求层序输出,可以不用队列,递归实现,只需将当前层数设为形参传入即可。
- 神仙资料推荐:LeetCode CookBook。 leetcode算法题,双百Go语言解法,国人编写,中文题解,很强大!。
- 位运算:X & (X-1) 清零最低位的1,X & -X => 得到最低位的1 。
- 记忆化搜索 ≈ 动态规划,只不过前者是 top-down,后者是 bottom-up。
- 贪心只能看到局部最优解,无法得到全局最优;而动规由于保存了过去的状态,因此能从全局的角度利用信息,求取全局最优解。此外,动规相比于遍历的暴力解法,做了剪枝的操作,只利用那些有用的信息。
- 写递归函数时,先处理继续递归的情况(因为占大多数),再处理终止递归的情况会更好。(循环语句同理)