面试经典算法28 - 翻转二叉树
LeetCode.226
公众号:阿Q技术站
问题描述
给你一棵二叉树的根节点 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
思路
递归
- 如果根节点为空,直接返回 nullptr。
- 交换根节点的左右子节点。
- 递归地对左子树和右子树进行翻转。
非递归
- 使用一个栈来存储待翻转的节点。
- 遍历栈中的节点,对于每个节点,交换其左右子节点,并将其左右子节点入栈。
- 直到栈为空为止。
图解
- 申请一个栈,将根节点放入栈中。
- 如果栈不为空,获取栈顶节点,弹出栈顶节点。
- 交换当前节点的左右节点,并将当前节点的左右节点入栈。
- 此时栈不为空,弹出栈顶节点。
- 交换当前节点的左右节点,并将当前节点的左右节点入栈。
- 栈不为空,弹出栈顶节点。
当前节点无子节点,不交换,也无需入栈。
- 栈不为空,弹出栈顶元素。
当前节点无子节点,不交换,也无需入栈。
- 栈不为空,弹出栈顶节点。
- 交换当前节点的左右节点,并将当前节点的左右节点入栈。
- 栈不为空,弹出栈顶节点。
当前节点无子节点,不交换,也无需入栈。
- 栈不为空,弹出栈顶节点。
当前节点无子节点,不交换,也无需入栈。
此时,栈为空,退出循环,并返回4。
参考代码
C++
递归
#include <iostream>
#include <queue>
using namespace std;
// 二叉树节点的定义
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
// 递归函数:翻转二叉树
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) {
return nullptr; // 如果根节点为空,直接返回 nullptr
}
// 交换根节点的左右子节点
TreeNode* temp = root->left;
root->left = root->right;
root->right = temp;
// 递归地对左右子树进行翻转
invertTree(root->left);
invertTree(root->right);
return root; // 返回翻转后的根节点
}
// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {
if (index >= nodes.size() || nodes[index] == -1) {
return nullptr; // 如果节点为空,则返回nullptr
}
TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点
root->left = createTree(nodes, 2 * index + 1); // 创建左子树
root->right = createTree(nodes, 2 * index + 2); // 创建右子树
return root; // 返回当前节点
}
// 销毁二叉树
void destroyTree(TreeNode* root) {
if (!root) return; // 如果根节点为空,直接返回
destroyTree(root->left); // 递归销毁左子树
destroyTree(root->right); // 递归销毁右子树
delete root; // 删除当前节点
}
// 中序遍历二叉树(测试用)
void inorderTraversal(TreeNode* root) {
if (root == nullptr) return;
inorderTraversal(root->left);
cout << root->val << " ";
inorderTraversal(root->right);
}
int main() {
vector<int> nodes = {4, 2, 7, 1, 3, 6, 9}; // 定义二叉树的先序遍历序列
TreeNode* root = createTree(nodes, 0); // 创建二叉树
cout << "翻转前的二叉树(中序遍历):" << endl;
inorderTraversal(root); // 输出翻转前的二叉树(中序遍历)
cout << endl;
root = invertTree(root); // 翻转二叉树
cout << "翻转后的二叉树(中序遍历):" << endl;
inorderTraversal(root); // 输出翻转后的二叉树(中序遍历)
cout << endl;
destroyTree(root); // 销毁二叉树
return 0;
}
非递归
#include <iostream>
#include <stack>
using namespace std;
// 二叉树节点的定义
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
// 非递归函数:翻转二叉树
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) {
return nullptr; // 如果根节点为空,直接返回 nullptr
}
stack<TreeNode*> stk; // 辅助栈,用于存储待翻转的节点
stk.push(root); // 将根节点入栈
while (!stk.empty()) {
TreeNode* node = stk.top(); // 获取栈顶节点
stk.pop(); // 弹出栈顶节点
// 交换当前节点的左右子节点
TreeNode* temp = node->left;
node->left = node->right;
node->right = temp;
// 将当前节点的左右子节点入栈
if (node->left) {
stk.push(node->left);
}
if (node->right) {
stk.push(node->right);
}
}
return root; // 返回翻转后的根节点
}
// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {
if (index >= nodes.size() || nodes[index] == -1) {
return nullptr; // 如果节点为空,则返回nullptr
}
TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点
root->left = createTree(nodes, 2 * index + 1); // 创建左子树
root->right = createTree(nodes, 2 * index + 2); // 创建右子树
return root; // 返回当前节点
}
// 销毁二叉树
void destroyTree(TreeNode* root) {
if (!root) return; // 如果根节点为空,直接返回
destroyTree(root->left); // 递归销毁左子树
destroyTree(root->right); // 递归销毁右子树
delete root; // 删除当前节点
}
// 中序遍历二叉树(测试用)
void inorderTraversal(TreeNode* root) {
if (root == nullptr) return;
inorderTraversal(root->left);
cout << root->val << " ";
inorderTraversal(root->right);
}
int main() {
vector<int> nodes = {4, 2, 7, 1, 3, 6, 9}; // 定义二叉树的先序遍历序列
TreeNode* root = createTree(nodes, 0); // 创建二叉树
cout << "翻转前的二叉树(中序遍历):" << endl;
inorderTraversal(root); // 输出翻转前的二叉树(中序遍历)
cout << endl;
root = invertTree(root); // 翻转二叉树
cout << "翻转后的二叉树(中序遍历):" << endl;
inorderTraversal(root); // 输出翻转后的二叉树(中序遍历)
cout << endl;
destroyTree(root); // 销毁二叉树
return 0;
}
Java
import java.util.*;
// 二叉树节点的定义
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
// 翻转二叉树的函数
public class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null; // 如果根节点为空,直接返回 null
}
Stack<TreeNode> stack = new Stack<>(); // 辅助栈,用于存储待翻转的节点
stack.push(root); // 将根节点入栈
while (!stack.isEmpty()) {
TreeNode node = stack.pop(); // 弹出栈顶节点
// 交换当前节点的左右子节点
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// 将当前节点的左右子节点入栈
if (node.left != null) {
stack.push(node.left);
}
if (node.right != null) {
stack.push(node.right);
}
}
return root; // 返回翻转后的根节点
}
// 创建二叉树的函数
public TreeNode createTree(Integer[] nodes, int index) {
if (index >= nodes.length || nodes[index] == null) {
return null; // 如果节点为空,则返回 null
}
TreeNode root = new TreeNode(nodes[index]); // 创建当前节点
root.left = createTree(nodes, 2 * index + 1); // 创建左子树
root.right = createTree(nodes, 2 * index + 2); // 创建右子树
return root; // 返回当前节点
}
// 销毁二叉树的函数
public void destroyTree(TreeNode root) {
if (root == null) return; // 如果根节点为空,直接返回
destroyTree(root.left); // 递归销毁左子树
destroyTree(root.right); // 递归销毁右子树
}
// 中序遍历二叉树(测试用)
public void inorderTraversal(TreeNode root) {
if (root == null) return;
inorderTraversal(root.left);
System.out.print(root.val + " ");
inorderTraversal(root.right);
}
public static void main(String[] args) {
Integer[] nodes = {4, 2, 7, 1, 3, 6, 9}; // 定义二叉树的先序遍历序列
Solution solution = new Solution();
TreeNode root = solution.createTree(nodes, 0); // 创建二叉树
System.out.println("翻转前的二叉树(中序遍历):");
solution.inorderTraversal(root); // 输出翻转前的二叉树(中序遍历)
System.out.println();
root = solution.invertTree(root); // 翻转二叉树
System.out.println("翻转后的二叉树(中序遍历):");
solution.inorderTraversal(root); // 输出翻转后的二叉树(中序遍历)
System.out.println();
solution.destroyTree(root); // 销毁二叉树
}
}
Python
# 二叉树节点的定义
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
# 翻转二叉树的函数
def invertTree(root: TreeNode) -> TreeNode:
if not root:
return None # 如果根节点为空,直接返回 None
stack = [root] # 辅助栈,用于存储待翻转的节点
while stack:
node = stack.pop() # 弹出栈顶节点
# 交换当前节点的左右子节点
node.left, node.right = node.right, node.left
# 将当前节点的左右子节点入栈
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
return root # 返回翻转后的根节点
# 创建二叉树的函数
def createTree(nodes, index):
if index >= len(nodes) or nodes[index] is None:
return None # 如果节点为空,则返回 None
root = TreeNode(nodes[index]) # 创建当前节点
root.left = createTree(nodes, 2 * index + 1) # 创建左子树
root.right = createTree(nodes, 2 * index + 2) # 创建右子树
return root # 返回当前节点
# 销毁二叉树的函数
def destroyTree(root):
if not root:
return # 如果根节点为空,直接返回
destroyTree(root.left) # 递归销毁左子树
destroyTree(root.right) # 递归销毁右子树
# 中序遍历二叉树(测试用)
def inorderTraversal(root):
if not root:
return
inorderTraversal(root.left)
print(root.val, end=" ")
inorderTraversal(root.right)
# 测试用例
nodes = [4, 2, 7, 1, 3, 6, 9] # 定义二叉树的先序遍历序列
root = createTree(nodes, 0) # 创建二叉树
print("翻转前的二叉树(中序遍历):")
inorderTraversal(root) # 输出翻转前的二叉树(中序遍历)
print()
root = invertTree(root) # 翻转二叉树
print("翻转后的二叉树(中序遍历):")
inorderTraversal(root) # 输出翻转后的二叉树(中序遍历)
print()
destroyTree(root) # 销毁二叉树