面试经典算法系列之二叉树13 -- 翻转二叉树

面试经典算法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

思路

递归
  1. 如果根节点为空,直接返回 nullptr。
  2. 交换根节点的左右子节点。
  3. 递归地对左子树和右子树进行翻转。
非递归
  1. 使用一个栈来存储待翻转的节点。
  2. 遍历栈中的节点,对于每个节点,交换其左右子节点,并将其左右子节点入栈。
  3. 直到栈为空为止。

图解

  1. 申请一个栈,将根节点放入栈中。

  1. 如果栈不为空,获取栈顶节点,弹出栈顶节点。

  1. 交换当前节点的左右节点,并将当前节点的左右节点入栈。

  1. 此时栈不为空,弹出栈顶节点。

  1. 交换当前节点的左右节点,并将当前节点的左右节点入栈。

  1. 栈不为空,弹出栈顶节点。

当前节点无子节点,不交换,也无需入栈。

  1. 栈不为空,弹出栈顶元素。

当前节点无子节点,不交换,也无需入栈。

  1. 栈不为空,弹出栈顶节点。

  1. 交换当前节点的左右节点,并将当前节点的左右节点入栈。

  1. 栈不为空,弹出栈顶节点。

当前节点无子节点,不交换,也无需入栈。

  1. 栈不为空,弹出栈顶节点。

当前节点无子节点,不交换,也无需入栈。

此时,栈为空,退出循环,并返回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)  # 销毁二叉树
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值