题目链接:226. 翻转二叉树
题目:
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
示例 1:
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
示例 2:
输入:root = [2,1,3]
输出:[2,3,1]
示例 3:
输入:root = []
输出:[]
提示:
- 树中节点数目范围在 [0, 100] 内
- -100 <= Node.val <= 100
解题思路:
本题需要翻转二叉树,如果要从整个二叉树来看,整个树以中间分割线进行翻转,翻转还真的挺复杂的。但是我们可以发现想要翻转它,其实就把每一个节点的左右孩子交换一下就可以了。关键在于遍历顺序,前中后序应该选哪一种遍历顺序? 遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果所,以本题使用前序、后序和层序遍历都可以,唯独中序遍历不太方便,因为中序遍历会把某些节点的左右孩子翻转两次!
方案一:递归
“一入递归深似海,从此offer是路人。”关于使用递归,很大一部分人都可能是得过且过,只要能通过代码结果检测,就万事大吉了。但是,这样并不能保证自己每次都能成功通过用递归解的题,而且很容易陷进逻辑里无法出来。所以,为了避免这种情况,我们就需要了解递归如何解题,这样我们以后解递归类的题就能很轻松的解决了。
在用递归解题方法前,先弄清楚该题的“递归三要素”,关于三要素我已经教你写递归——递归三部曲在这篇文章里阐述了。
这里采用前序遍历,本题的三部曲是:
(1)确定递归的参数和返回值:因为我们是交换左右孩子,所以参数是节点就可以;返回值不需要什么,直接void类型就行,但是我们可以用题目给的函数,这样代码更简洁,因为我们也不使用返回值。
TreeNode* invertTree(TreeNode* root) {}
(2)确定递归的终止条件:节点为空的时候就返回。
if (root == NULL) return NULL;
(3)确定递归的单层逻辑:交换左右孩子,由于是前序遍历,则先递归左子树后递归右子树。
swap(root->left, root->right); //交换左右孩子
invertTree(root->left); //递归左子树
invertTree(root->right); //递归右子树
代码(c++):
/**
* 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:
//1.确定递归的参数和返回值
//参数:当前节点的左右孩子节点,返回值:void就行,但是直接用题目给的函数也可以
TreeNode* invertTree(TreeNode* root) {
//2.确定递归终止条件
//节点为空时返回
if (root == NULL) return NULL;
//3.确定递归单层逻辑
//交换左右孩子,由于是前序遍历,则先递归左子树后递归右子树
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
方案二:迭代
1、深度优先遍历
这里用栈来进行前序遍历
代码(c++):
/**
* 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:
TreeNode* invertTree(TreeNode* root) {
stack<TreeNode*> stk;
if (root) stk.push(root);
while (!stk.empty()) {
TreeNode* cur = stk.top();
stk.pop();
//交换左右孩子
swap(cur->left, cur->right);
//将左右孩子压栈
if (cur->right) stk.push(cur->right);
if (cur->left) stk.push(cur->left);
}
return root;
}
};
2、广度优先遍历
这里用队列进行层序遍历
代码(c++):
/**
* 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:
TreeNode* invertTree(TreeNode* root) {
queue<TreeNode*> que;
if (root) que.push(root);
while (!que.empty()) {
int size = que.size(); //记录队列的长度(队列不定长)
for (int i = 0; i < size; ++i) { //遍历该层的所有节点
TreeNode* cur = que.front();
que.pop();
//交换左右孩子
swap(cur->left, cur->right);
//将左右孩子放入队列
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
}
return root;
}
};