代码随想录第五十八期day13
题目一:144. 二叉树的前序遍历
题目描述:给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
解释:
示例 2:
输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]
输出:[1,2,4,5,6,7,3,8,9]
解释:
示例 3:
输入:root = []
输出:[]
示例 4:
输入:root = [1]
输出:[1]
提示:
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
进阶:递归算法很简单,你可以通过迭代算法完成吗?
解析:本题递归算法很简单,所以用一个递归就能完成,写递归时要注意终止条件,不能写成没用终止条件的递归,本题终止条件就是当节点为空时候,就结束递归。具体代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void digui(TreeNode* cur,vector<int> &vec){
if(cur == NULL)return;
vec.push_back(cur->val);
digui(cur->left,vec);
digui(cur->right,vec);
}
vector<int> preorderTraversal(TreeNode* root) {
//递归前序遍历二叉树
vector<int>a;
digui(root,a);
return a;
}
};
解法二:迭代法前序遍历二叉树,首先递归也是使用栈来实现的递归,基于此,我们也可以使用栈来对二叉树进行前序遍历,由于栈是后进先出,所以我们要先压入右子树,再压入左子树,这样才能保证先访问左字数,具体代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*>a;
vector<int>result;
if(root == NULL)return result;
a.push(root);
TreeNode* p=root;
//TreeNode* q=root;
while(!a.empty()){
p=a.top();
a.pop();
result.push_back(p->val);
if(p->right !=NULL)a.push(p->right);
if(p->left != NULL)a.push(p->left);
}
return result;
}
};
题目二:145. 二叉树的后序遍历
题目描述:给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
示例 1:
输入:root = [1,null,2,3]
输出:[3,2,1]
解释:
示例 2:
输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]
输出:[4,6,7,5,2,9,8,3,1]
解释:
示例 3:
输入:root = []
输出:[]
示例 4:
输入:root = [1]
输出:[1]
提示:
树中节点的数目在范围 [0, 100] 内
-100 <= Node.val <= 100
进阶:递归算法很简单,你可以通过迭代算法完成吗?
解析:其实二叉树的前中后递归遍历很简单,就是交换代码位置即可,本题的后续遍历,那就把访问节点在递归函数里面写在找节点的后面即可,后面还有一道是中序遍历的,就把访问节点放在中间即可,具体后序遍历代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void digui(TreeNode* cur,vector<int> &vec){
if(cur == NULL)return;
digui(cur->left,vec);
digui(cur->right,vec);
vec.push_back(cur->val);
}
vector<int> postorderTraversal(TreeNode* root) {
//递归前序遍历二叉树
vector<int>a;
digui(root,a);
return a;
}
};
解法二:迭代法后序遍历二叉树;由上一题我们知道了迭代遍历二叉树,现在我们也是在里面修改一下位置即可。本题也是初次看见,具体可以看Carl哥讲解不用去具体实现什么,在前序上直接改一下就行,只能说太强了,具体代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
stack<TreeNode*>a;
vector<int>result;
if(root == NULL)return result;
a.push(root);
TreeNode* p=root;
while(!a.empty()){
p=a.top();
a.pop();
result.push_back(p->val);
if(p->left != NULL)a.push(p->left);
if(p->right !=NULL)a.push(p->right);
}
reverse(result.begin(),result.end());
return result;
}
};
题目三:94. 二叉树的中序遍历
题目描述:给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例 1:
输入:root = [1,null,2,3]
输出:[1,3,2]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
提示:
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
解析:递归算法很简单,具体只要在前序和后序里面的代码改一下位置即可,具体代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void digui(TreeNode* cur,vector<int> &vec){
if(cur == NULL)return;
digui(cur->left,vec);
vec.push_back(cur->val);
digui(cur->right,vec);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int>a;
digui(root,a);
return a;
}
};
下面我们介绍迭代算法,本题的迭代算法和前序和后序不一样,对于中序遍历来说,先访问左子树在访问根节点最后访问右节点,所以循环里面我们要先找到最左端点节点,才能继续下一步操作,具体代码如下,由于写错了,然后问豆包,所以它给出了正确的写法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> stk;
TreeNode* curr = root; // 独立指针,避免污染栈
while (curr || !stk.empty()) { // 循环条件:curr非空 或 栈非空
// 1. 向左走到尽头,沿途压栈(含当前节点)
while (curr) {
stk.push(curr);
curr = curr->left;
}
// 2. 取出栈顶(最左节点),处理「根」
curr = stk.top();
stk.pop();
res.push_back(curr->val);
// 3. 转向右子树(无需压栈,外层循环会重新处理)
curr = curr->right;
}
return res;
}
};