二叉树的遍历
:::info 二叉树的遍历分为:
- 前序:root-leftTree-rightTree
- 中序:leftTree-root-rightTree
后续:leftTree-rightTree-root ::: 这些顺序的分别在于何时处理当前节点;在dfs遍历的过程中,一个节点会被经过3次;
void traverse(TreeNode* root){//first time---preordertraverse(root->left);//second time---inordertraverse(root->right);//third time---postorder}
:::tips 三种遍历各有特点:
前序:不需要知道子树的内容
- 中序:已经知道左子树的内容
- 后序:知道了两个子树的内容
递归的题
:::info
二叉树有两种题:一种要递归遍历,一种要分情况讨论;
递归的题如果需要知道下面子树的情况,大多是后序遍历!
:::
递归改迭代
递归改迭实际上不会减少多少空间复杂度,只是自己操作栈或队列来替代了系统压栈
stack<TreeNode*> st;if(root==nullptr)return;st.push(st);while(!st.empty()){TreeNode* cur=st.top();st.pop();if(cur->right!=nullptr) st.push(cur->right);//先入后出if(cur->left!=nullptr) st.push(cur->left);//处理cur节点}
:::info 前序用的是stack :::
stack<TreeNode*> st;if(root==nullptr)return;st.push(st);while(!st.empty()){TreeNode* cur=st.top();st.pop();if(cur->left!=nullptr) st.push(cur->right);//先入后出if(cur->right!=nullptr) st.push(cur->right);//处理cur节点vec.push_back(cur->val);}reverse(vec.begin(),vec.end));
:::danger 只能是用数组存了后reverse;如果不是遍历而是做其他操作,那么需要递归吧 :::
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;}};
:::tips 中序和前序后续都不一样! :::
层序遍历(BFS)
:::info 层序遍历的核心是会用到额外的容器去存下下一层需要遍历的节点;
- 二叉树里有,图中也有、二维数组里也可以有
二叉树中用queue:队列,先入先出。 :::
//input TreeNode* rootif(root==nullptr)return {};queue<TreeNode*> que;vector<int> vec;que.push(root);while(!que.empty()){int sz=que.size();//先要去确定当前一层有多少节点for(int i=0;i<sz;i++){TreeNode*cur=que.front();que.pop();if(cur->left!=nullptr) que.push(cur->left);if(cur->right!=nullptr) que.push(cur->right);vec.push_back(cur->val);//处理当前节点}}
:::info 层序遍历需要注意的点:
循环中不能用
que.size()因为在每轮迭代中都会插入节点,会变,需要在每一层开始前求出size可以改变的地方有插入节点的顺序:先左后右还是先右后左 :::
二叉树中的回溯
何时需要返回值?
如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
- 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先(opens new window)中介绍)
- 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)
