二叉树---翻转二叉树

🔥个人主页: Milestone-里程碑

❄️个人专栏: <<力扣hot100>> <<C++>><<Linux>>

<<Git>><<MySQL>>

🌟心向往之行必能至

先看题目:

给定一棵二叉树,翻转这棵二叉树,并返回其根节点。所谓翻转,就是把每个节点的左子树和右子树互换,一层一层递归完成即可。

一、题目分析

翻转二叉树的核心逻辑只有两步:

  1. 终止条件 :如果当前节点是空节点(nullptr),直接返回,不用处理。
  2. 递归处理:先交换当前节点的左右孩子,再递归翻转左子树、递归翻转右子树。

举个直观例子:

plaintext

复制代码
原树:
     4
   /   \
  2     7
 / \   / \
1   3 6   9

翻转后:
     4
   /   \
  7     2
 / \   / \
9   6 3   1

每个节点的左右子树都完成了互换,完美符合要求。

二、完整 C++ 代码(递归版)

这是最简洁、最容易理解的递归实现,也是面试首选写法:

cpp

运行

复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        // 递归终止条件:空节点直接返回
        if(root == nullptr) return nullptr;
        
        // 交换当前节点的左右孩子
        TreeNode* temp = root->left;
        root->left = root->right;
        root->right = temp;
        
        // 递归翻转左子树
        invertTree(root->left);
        // 递归翻转右子树
        invertTree(root->right);
        
        // 返回翻转后的根节点
        return root;
    }
};

三、代码逐行解析

我把代码拆解开,一步步讲清楚每一行的作用:

1. 递归终止条件

cpp

运行

复制代码
if(root == nullptr) return nullptr;
  • 如果当前节点是空节点,没有左右孩子可以交换,直接返回,避免空指针报错。
  • 这是递归的出口,所有递归题都必须有明确的终止条件。

2. 交换当前节点的左右孩子

cpp

运行

复制代码
TreeNode* temp = root->left;
root->left = root->right;
root->right = temp;
  • 用一个临时指针temp暂存左孩子。
  • 把右孩子赋值给左指针,左孩子赋值给右指针,完成当前节点的左右翻转

3. 递归处理子树

cpp

运行

复制代码
invertTree(root->left);
invertTree(root->right);
  • 交换完当前节点后,它的左、右子树还没翻转,所以递归调用函数处理左、右子树。
  • 递归会一直深入到叶子节点,再逐层返回处理,最终整棵树完成翻转。

4. 返回根节点

cpp

运行

复制代码
return root;
  • 最终返回翻转后的二叉树根节点,符合题目要求。

四、复杂度分析

  1. 时间复杂度:O(n)二叉树的每个节点都会被访问一次,所以时间复杂度和节点数成正比。

  2. 空间复杂度:O(h)h 是二叉树的高度,递归调用栈的深度等于树的高度。

    • 最坏情况(斜树):h=n,空间复杂度 O(n)
    • 最好情况(平衡二叉树):h=logn,空间复杂度 O(logn)

五、递归思想总结

这道题完美体现了递归三要素

  1. 确定递归函数的功能:翻转以 root 为根的二叉树。
  2. 确定递归终止条件:节点为空时返回。
  3. 确定递归递推公式:交换当前节点左右孩子 + 递归翻转左右子树。

只要掌握这个思路,二叉树的绝大多数递归题都能轻松搞定~

六、小拓展:迭代版(广度优先)

如果面试要求不用递归,可以用队列 + BFS实现,思路是层序遍历每个节点,逐个交换左右孩子:

cpp

运行

复制代码
TreeNode* invertTree(TreeNode* root) {
    if(!root) return nullptr;
    queue<TreeNode*> q;
    q.push(root);
    while(!q.empty()){
        TreeNode* node = q.front();
        q.pop();
        // 交换当前节点左右孩子
        swap(node->left, node->right);
        if(node->left) q.push(node->left);
        if(node->right) q.push(node->right);
    }
    return root;
}

总结

  1. 翻转二叉树核心:交换当前节点左右孩子 + 递归翻转子树
  2. 递归代码极简,面试首选,时间复杂度 O(n)。
  3. 掌握递归三要素,二叉树递归题一通百通。
相关推荐
闻缺陷则喜何志丹2 小时前
【排序】P6149 [USACO20FEB] Triangles S|普及+
c++·算法·排序·洛谷
tankeven2 小时前
HJ178 【模板】双指针
c++·算法
Rsun045512 小时前
16、Java 迭代器模式从入门到实战
java·开发语言·迭代器模式
We་ct2 小时前
Git 核心知识点全解析
开发语言·前端·git·gitee·github
iDao技术魔方2 小时前
Bun v1.3.12 深度解析:新特性、性能优化与实战指南
开发语言·javascript·visual studio code
charlie1145141912 小时前
嵌入式C++工程实践——第13篇:第一次重构 —— enum class取代宏,类型安全的开始
开发语言·c++·vscode·stm32·安全·重构·现代c++
jiayong232 小时前
第 13 课:分页、页码状态和 URL 同步
开发语言·前端·javascript·vue.js·学习
CHANG_THE_WORLD3 小时前
C++ 文件读取函数完全指南
开发语言·c++
6Hzlia3 小时前
【Hot 100 刷题计划】 LeetCode 300. 最长递增子序列 | C++ 动态规划 & 贪心二分
c++·leetcode·动态规划