代码随想录阅读笔记-二叉树【翻转二叉树】

题目

翻转一棵二叉树。

思路

如果要从整个树来看,翻转还真的挺复杂,整个树以中间分割线进行翻转,如图:

可以发现想要翻转它,其实就把每一个节点的左右孩子交换一下就可以了。

关键在于遍历顺序,前中后序应该选哪一种遍历顺序?

遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果。

注意只要把每一个节点的左右孩子翻转一下,就可以达到整体翻转的效果

这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!建议拿纸画一画,就理解了

那么层序遍历可以不可以呢?依然可以的!只要把每一个节点的左右孩子翻转一下的遍历方式都是可以的!

下面便和之前的遍历一样,从递归和迭代两种角度出发解题

递归法

我们下文以前序遍历为例,通过动画来看一下翻转的过程:

我们来看一下递归三部曲:

1、确定递归函数的参数和返回值

参数就是要传入节点的指针,不需要其他参数了,通常此时定下来主要参数,如果在写递归的逻辑中发现还需要其他参数的时候,随时补充。

返回值的话其实也不需要,但是题目中给出的要返回root节点的指针,可以直接使用题目定义好的函数,所以就函数的返回类型为TreeNode*

cpp 复制代码
TreeNode* invertTree(TreeNode* root)

2、确定终止条件

当前节点为空的时候,就返回

cpp 复制代码
if (root == NULL) return root;

3、确定单层递归的逻辑

因为是前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。

cpp 复制代码
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);

基于这递归三步法,C++代码如下:

cpp 复制代码
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        swap(root->left, root->right);  // 中
        invertTree(root->left);         // 左
        invertTree(root->right);        // 右
        return root;
    }
};

迭代法

深度优先遍历

之前的博客中给出了前中后序迭代方式的写法,所以本题可以很轻松的写出如下迭代法的代码:

C++代码迭代法(前序遍历)

cpp 复制代码
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()) {
            TreeNode* node = st.top();              // 中
            st.pop();
            swap(node->left, node->right);
            if(node->right) st.push(node->right);   // 右
            if(node->left) st.push(node->left);     // 左
        }
        return root;
    }
};

如果这个代码看不懂的话可以再回顾一下代码随想录阅读笔记-二叉树【迭代遍历】-CSDN博客

我们在代码随想录阅读笔记-二叉树【统一迭代法】-CSDN博客中介绍了统一的写法,所以,本题也只需将文中的代码少做修改便可。

C++代码如下统一迭代法(前序遍历)

cpp 复制代码
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                if (node->right) st.push(node->right);  // 右
                if (node->left) st.push(node->left);    // 左
                st.push(node);                          // 中
                st.push(NULL);
            } else {
                st.pop();
                node = st.top();
                st.pop();
                swap(node->left, node->right);          // 节点处理逻辑
            }
        }
        return root;
    }
};
广度优先遍历

也就是层序遍历,层数遍历也是可以翻转这棵树的,因为层序遍历也可以把每个节点的左右孩子都翻转一遍,代码如下:

cpp 复制代码
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                swap(node->left, node->right); // 节点处理
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return root;
    }
};
相关推荐
刚学HTML24 分钟前
leetcode 05 回文字符串
算法·leetcode
Yan.love37 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
AC使者43 分钟前
#B1630. 数字走向4
算法
冠位观测者1 小时前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
古希腊掌管学习的神2 小时前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca2 小时前
洛谷 P1706 全排列问题 C语言
算法
浊酒南街2 小时前
决策树(理论知识1)
算法·决策树·机器学习
就爱学编程2 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
oneouto2 小时前
selenium学习笔记(二)
笔记·学习·selenium
学术头条2 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学