代码细节
- 循环判断条件的每一个改变,都要思考是否会影响循环结束。最好保证循环里只有一个位置对循环控制变量++。
- 下标的每一个改变,都要考虑越界。
- 指针的每一个改变,都要考虑为null。每一次取值,都要先考虑null。
- 加和乘要注意溢出!
- 先模拟一遍 ->伪代码->边界测试->写代码
小技巧
- 最小值:所有值为int时,用
Long.MIN_VALUE
存储初始值。 - 递归返回值用void,再写一个函数将要求的返回值变成参数。
- 判断x∈[a, b]:
if(((long)x-a)*(x-b)<=0)
。用long防止溢出。
二叉树的迭代遍历
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur != NULL || !st.empty()) {
if (cur != NULL) { // 指针来访问节点,访问到最底层
st.push(cur); // 将访问的节点放进栈
cur = cur->left; // 左
} else {
cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
st.pop();
result.push_back(cur->val); // 中
cur = cur->right; // 右
}
}
return result;
}
};
二叉树的统一迭代法
二分法
- 二分法返回什么?
当i=j时,相遇点之前一定比target小,相遇点之后一定比target大。此时,只有相遇点与target大小关系未知。
最终,i一定会指向第一个比target大的点,即i左边都比target小。
j一定会指向第一个比target小的点,即j右边都比target大。 根据题目要求返回所需数据。
值的改变与比较应该放在一处
160. 相交链表
如果把 pA = pA == nullptr ? headB : pA->next;
拆成如下两行,那么
pA = pA->next;
会改变pA的值,可能出现pA = pB;
需要判断一次;pA = headB;
会改变pA的值,可能出现pA = pB;
需要判断一次;
所以需要图中所示的两个判断。
核心在于,当 pA == nullptr ;
时,出现了错配,不应该是为空的pA与此时的pB比较,而是headB与此时的pB比较。分开写无法解决这种错配,只能用continue或者两次比较,通过冗余一次比较实现,导致代码繁琐。
而且,当pA和pB同时为空,应该是满足pA==pB。
递归函数什么时候需要返回值?
递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:
- 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
- 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)
- 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)
二叉树
- 二叉树的高度和深度不同。高度用递归,深度用层遍。