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

题目

翻转一棵二叉树。

思路

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

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

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

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

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

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

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

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

递归法

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

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

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;
    }
};
相关推荐
我命由我123453 分钟前
SSL 协议(HTTPS 协议的关键)
网络·经验分享·笔记·学习·https·ssl·学习方法
希望有朝一日能如愿以偿31 分钟前
力扣题解(飞机座位分配概率)
算法·leetcode·职场和发展
丶Darling.42 分钟前
代码随想录 | Day26 | 二叉树:二叉搜索树中的插入操作&&删除二叉搜索树中的节点&&修剪二叉搜索树
开发语言·数据结构·c++·笔记·学习·算法
JustCouvrir1 小时前
代码随想录算法训练营Day15
算法
小小工匠1 小时前
加密与安全_HOTP一次性密码生成算法
算法·安全·htop·一次性密码
中文英文-我选中文1 小时前
排序算法的理解
算法·排序算法
我明天再来学Web渗透1 小时前
【hot100-java】【二叉树的层序遍历】
java·开发语言·数据库·sql·算法·排序算法
结衣结衣.2 小时前
python中的函数介绍
java·c语言·开发语言·前端·笔记·python·学习
LN-ZMOI2 小时前
c++学习笔记1
c++·笔记·学习
数据分析螺丝钉2 小时前
力扣第240题“搜索二维矩阵 II”
经验分享·python·算法·leetcode·面试