翻转二叉树
题目要求
你需要编写一个函数,该函数接收一个二叉树的根节点 root
作为参数。你的任务是将这棵二叉树进行翻转,即交换每个节点的左右子节点,然后返回翻转后的二叉树的根节点。
解题思路
翻转二叉树是一道经典的二叉树问题,可以通过递归或迭代的方式来解决。以下是解题的基本思路:
-
递归法:
- 检查当前节点是否为空,如果为空,则不需要进行任何操作。
- 递归地对当前节点的左子树进行翻转。
- 递归地对当前节点的右子树进行翻转。
- 交换当前节点的左右子节点。
- 最后返回当前节点(现在它已经成为了翻转后的根节点)。
-
迭代法:
- 使用一个栈或队列来存储所有需要交换子节点的树节点。
- 将根节点放入栈或队列中。
- 当栈或队列不为空时,循环执行以下操作:
- 取出一个节点。
- 交换这个节点的左右子节点。
- 如果左子节点不为空,将它加入栈或队列。
- 如果右子节点不为空,将它加入栈或队列。
- 继续这个过程直到栈或队列为空,这时所有节点都已经翻转。
- 返回最初放入栈或队列的根节点,它现在是翻转后的根节点。
在实际编码时,递归法的代码通常更简洁,但是迭代法在处理非常深的树时可能会有更好的性能,因为它不会受到调用栈大小的限制。
Golang 版本
package main
import "fmt"
// TreeNode is a structure for tree nodes
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// invertTree function inverts a binary tree
func invertTree(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
// Swap the left and right children
root.Left, root.Right = root.Right, root.Left
// Recursively invert the left subtree
invertTree(root.Left)
// Recursively invert the right subtree
invertTree(root.Right)
return root
}
// Helper function to print the tree in-order (for verification)
func printTree(root *TreeNode) {
if root == nil {
return
}
printTree(root.Left)
fmt.Print(root.Val, " ")
printTree(root.Right)
}
func main() {
// Example usage:
// Constructing a binary tree:
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
root := &TreeNode{1,
&TreeNode{2,
&TreeNode{4, nil, nil},
&TreeNode{5, nil, nil}},
&TreeNode{3,
&TreeNode{6, nil, nil},
&TreeNode{7, nil, nil}}}
fmt.Println("Original tree in-order:")
printTree(root)
fmt.Println()
invertedRoot := invertTree(root)
fmt.Println("Inverted tree in-order:")
printTree(invertedRoot)
fmt.Println()
}
这段代码定义了一个TreeNode
结构体,实现了一个invertTree
函数来翻转二叉树,并提供了一个printTree
辅助函数来按顺序打印树的节点值,以便验证翻转是否正确。main
函数中创建了一个简单的二叉树,并展示了翻转前后的结果。
C++版本
#include <iostream>
using namespace std;
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) {
return nullptr;
}
// Swap the left and right children
TreeNode* temp = root->left;
root->left = root->right;
root->right = temp;
// Recursively invert the left subtree
invertTree(root->left);
// Recursively invert the right subtree
invertTree(root->right);
return root;
}
};
// Helper function to print the tree in-order (for verification)
void printTree(TreeNode* root) {
if (root == nullptr) {
return;
}
printTree(root->left);
cout << root->val << " ";
printTree(root->right);
}
int main() {
// Example usage:
// Constructing a binary tree:
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
TreeNode *root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
root->right->left = new TreeNode(6);
root->right->right = new TreeNode(7);
cout << "Original tree in-order: ";
printTree(root);
cout << endl;
Solution solution;
TreeNode *invertedRoot = solution.invertTree(root);
cout << "Inverted tree in-order: ";
printTree(invertedRoot);
cout << endl;
// Clean up memory if needed
// Remember to delete the nodes of the tree to prevent memory leaks
// This part is omitted for brevity
return 0;
}
这段代码定义了一个TreeNode
结构体和一个Solution
类,其中包含了invertTree
方法来翻转二叉树。还有一个printTree
辅助函数用于按顺序打印树的节点值,以便验证翻转是否正确。main
函数中创建了一个简单的二叉树,并展示了翻转前后的结果。注意,在实际应用中,你可能需要在程序结束前删除所有动态分配的节点,以避免内存泄漏。这部分代码在这里为了简洁而省略。
Python 版本
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if root is None:
return None
# Swap the left and right children
root.left, root.right = root.right, root.left
# Recursively invert the left and right subtree
self.invertTree(root.left)
self.invertTree(root.right)
return root
# Helper function to print the tree in-order (for verification)
def printTree(root: TreeNode):
if root is not None:
printTree(root.left)
print(root.val, end=' ')
printTree(root.right)
# Example usage:
if __name__ == "__main__":
# Constructing a binary tree:
# 1
# / \
# 2 3
# / \ / \
# 4 5 6 7
root = TreeNode(1,
TreeNode(2, TreeNode(4), TreeNode(5)),
TreeNode(3, TreeNode(6), TreeNode(7)))
print("Original tree in-order:")
printTree(root)
print()
solution = Solution()
invertedRoot = solution.invertTree(root)
print("Inverted tree in-order:")
printTree(invertedRoot)
print()
这段代码定义了一个TreeNode
类用于表示二叉树的节点,以及一个Solution
类,其中包含了invertTree
方法来翻转二叉树。还有一个printTree
辅助函数用于按顺序打印树的节点值,以便验证翻转是否正确。在__main__
部分,创建了一个简单的二叉树,并展示了翻转前后的结果。
Java 版本
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
// Swap the left and right children
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
// Recursively invert the left and right subtree
invertTree(root.left);
invertTree(root.right);
return root;
}
}
// Helper function to print the tree in-order (for verification)
class BinaryTreePrinter {
public void printTree(TreeNode root) {
if (root != null) {
printTree(root.left);
System.out.print(root.val + " ");
printTree(root.right);
}
}
}
public class Main {
public static void main(String[] args) {
// Example usage:
// Constructing a binary tree:
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
root.right.left = new TreeNode(6);
root.right.right = new TreeNode(7);
BinaryTreePrinter printer = new BinaryTreePrinter();
System.out.print("Original tree in-order: ");
printer.printTree(root);
System.out.println();
Solution solution = new Solution();
TreeNode invertedRoot = solution.invertTree(root);
System.out.print("Inverted tree in-order: ");
printer.printTree(invertedRoot);
System.out.println();
}
}
这段代码定义了一个TreeNode
类用于表示二叉树的节点,一个Solution
类包含了invertTree
方法来翻转二叉树,以及一个BinaryTreePrinter
类包含了printTree
方法用于按顺序打印树的节点值,以便验证翻转是否正确。在Main
类的main
方法中,创建了一个简单的二叉树,并展示了翻转前后的结果。
Rust 版本
use std::rc::Rc; use std::cell::RefCell; // Definition for a binary tree node. #[derive(Debug, PartialEq, Eq)] pub struct TreeNode { pub val: i32, pub left: Option<Rc<RefCell<TreeNode>>>, pub right: Option<Rc<RefCell<TreeNode>>>, } impl TreeNode { #[inline] pub fn new(val: i32) -> Self { TreeNode { val, left: None, right: None, } } } pub struct Solution {} impl Solution { pub fn invert_tree(root: Option<Rc<RefCell<TreeNode>>>) -> Option<Rc<RefCell<TreeNode>>> { if let Some(node) = root.clone() { let left = node.borrow().left.clone(); let right = node.borrow().right.clone(); node.borrow_mut().left = Self::invert_tree(right); node.borrow_mut().right = Self::invert_tree(left); } root } } fn main() { let root = Some(Rc::new(RefCell::new(TreeNode::new(1)))); let left = Some(Rc::new(RefCell::new(TreeNode::new(2)))); let right = Some(Rc::new(RefCell::new(TreeNode::new(3)))); let left_left = Some(Rc::new(RefCell::new(TreeNode::new(4)))); let left_right = Some(Rc::new(RefCell::new(TreeNode::new(5)))); let right_left = Some(Rc::new(RefCell::new(TreeNode::new(6)))); let right_right = Some(Rc::new(RefCell::new(TreeNode::new(7)))); if let Some(ref root_node) = root { root_node.borrow_mut().left = left; root_node.borrow_mut().right = right; if let Some(ref left_node) = root_node.borrow().left { left_node.borrow_mut().left = left_left; left_node.borrow_mut().right = left_right; } if let Some(ref right_node) = root_node.borrow().right { right_node.borrow_mut().left = right_left; right_node.borrow_mut().right = right_right; } } println!("Original tree: {:?}", root); let inverted_root = Solution::invert_tree(root); println!("Inverted tree: {:?}", inverted_root); }
这段代码使用 Rust 语言定义了一个二叉树节点结构体TreeNode
和一个解决方案结构体Solution
,其中包含了invert_tree
方法来翻转二叉树。在main
函数中,创建了一个简单的二叉树,并展示了翻转前后的结果。Rust 版本的代码使用了Rc
和RefCell
来实现可变性和所有权共享,这是 Rust 语言特有的特性。
总结
上面给出了针对翻转二叉树问题的不同编程语言的解法示例。无论是使用递归还是迭代,解决方案的核心思想都是交换每个节点的左右子节点,从而实现整棵二叉树的翻转。每种语言的代码示例都展示了如何定义二叉树节点的数据结构,以及如何实现翻转二叉树的算法。这些示例为不同语言的开发者提供了参考,帮助他们理解并实现翻转二叉树的算法。