【数据结构与算法】二叉树大总结

二叉树 20 道经典题,一篇讲透所有套路(附完整代码示例)

二叉树是算法学习中最核心的数据结构之一,它几乎贯穿了结构理解、递归、动态规划、搜索和路径问题 的各个方面。如果你想在算法面试或者竞赛中拔高,二叉树的题型必须彻底掌握。本篇文章将通过 20 道经典题,帮你建立一套完整的二叉树解题思路体系


一、建树问题

题目 1:前序 + 中序建树

核心思路:

  1. 前序第一个节点是根

  2. 在中序中找到根,划分左右子树

  3. 递归构建左右子树

示例代码:

复制代码
TreeNode* buildTree(string preorder, string inorder, unordered_map<char,int>& mp, int preStart, int inStart, int inEnd) {
    if (preStart >= preorder.size() || inStart > inEnd) return nullptr;
    char rootVal = preorder[preStart];
    TreeNode* root = new TreeNode(rootVal);
    int pos = mp[rootVal];
    root->left = buildTree(preorder, inorder, mp, preStart+1, inStart, pos-1);
    root->right = buildTree(preorder, inorder, mp, preStart+pos-inStart+1, pos+1, inEnd);
    return root;
}

题目 2:中序 + 后序建树

核心与前序类似,只是根节点是后序的最后一个。


二、遍历套路

题目 3:前序遍历

复制代码
void preorder(TreeNode* root) {
    if (!root) return;
    cout << root->val;
    preorder(root->left);
    preorder(root->right);
}

题目 4:中序遍历

复制代码
void inorder(TreeNode* root) {
    if (!root) return;
    inorder(root->left);
    cout << root->val;
    inorder(root->right);
}

题目 5:后序遍历

复制代码
void postorder(TreeNode* root) {
    if (!root) return;
    postorder(root->left);
    postorder(root->right);
    cout << root->val;
}

题目 6:层序遍历(BFS)

复制代码
vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> res;
    if (!root) return res;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty()) {
        int sz = q.size();
        vector<int> level;
        for (int i = 0; i < sz; i++) {
            TreeNode* node = q.front(); q.pop();
            level.push_back(node->val);
            if (node->left) q.push(node->left);
            if (node->right) q.push(node->right);
        }
        res.push_back(level);
    }
    return res;
}

三、树的变形问题

题目 7:翻转二叉树

复制代码
TreeNode* invertTree(TreeNode* root) {
    if (!root) return nullptr;
    swap(root->left, root->right);
    invertTree(root->left);
    invertTree(root->right);
    return root;
}

题目 8:对称二叉树

复制代码
bool isSymmetric(TreeNode* root) {
    if (!root) return true;
    return isMirror(root->left, root->right);
}

bool isMirror(TreeNode* t1, TreeNode* t2) {
    if (!t1 && !t2) return true;
    if (!t1 || !t2) return false;
    return (t1->val==t2->val) && isMirror(t1->left, t2->right) && isMirror(t1->right, t2->left);
}

题目 9:右视图

复制代码
vector<int> rightSideView(TreeNode* root) {
    vector<int> res;
    if (!root) return res;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty()) {
        int sz = q.size();
        for (int i = 0; i < sz; i++) {
            TreeNode* node = q.front(); q.pop();
            if (i == sz-1) res.push_back(node->val);
            if (node->left) q.push(node->left);
            if (node->right) q.push(node->right);
        }
    }
    return res;
}

题目 10:最大路径和

复制代码
int maxPathSum(TreeNode* root) {
    int max_sum = INT_MIN;
    function<int(TreeNode*)> dfs = [&](TreeNode* node){
        if(!node) return 0;
        int left = max(0, dfs(node->left));
        int right = max(0, dfs(node->right));
        max_sum = max(max_sum, left+right+node->val);
        return node->val + max(left, right);
    };
    dfs(root);
    return max_sum;
}

四、二叉搜索树特有题

题目 11:验证 BST

复制代码
bool isValidBST(TreeNode* root) {
    return helper(root, LONG_MIN, LONG_MAX);
}

bool helper(TreeNode* node, long min_val, long max_val){
    if(!node) return true;
    if(node->val<=min_val || node->val>=max_val) return false;
    return helper(node->left,min_val,node->val) && helper(node->right,node->val,max_val);
}

题目 12:第 k 小元素

复制代码
int kthSmallest(TreeNode* root, int k) {
    int count=0, result=0;
    function<void(TreeNode*)> inorder = [&](TreeNode* node){
        if(!node) return;
        inorder(node->left);
        count++;
        if(count==k) { result=node->val; return; }
        inorder(node->right);
    };
    inorder(root);
    return result;
}

题目 13:最小高度 BST(有序数组建树)

复制代码
TreeNode* sortedArrayToBST(vector<int>& nums, int l, int r) {
    if(l>r) return nullptr;
    int mid = l + (r-l)/2;
    TreeNode* root = new TreeNode(nums[mid]);
    root->left = sortedArrayToBST(nums,l,mid-1);
    root->right = sortedArrayToBST(nums,mid+1,r);
    return root;
}

五、树的路径类问题

题目 14:路径总和

判断是否存在根到叶子节点路径和等于 target:

复制代码
bool hasPathSum(TreeNode* root, int sum) {
    if(!root) return false;
    if(!root->left && !root->right) return root->val==sum;
    return hasPathSum(root->left,sum-root->val) || hasPathSum(root->right,sum-root->val);
}

题目 15:所有路径

复制代码
void dfs(TreeNode* root,int sum,vector<int>& path, vector<vector<int>>& res){
    if(!root) return;
    path.push_back(root->val);
    if(!root->left && !root->right) res.push_back(path);
    dfs(root->left,sum,path,res);
    dfs(root->right,sum,path,res);
    path.pop_back();
}

六、特殊树形操作

题目 16:展开二叉树为链表

复制代码
void flatten(TreeNode* root) {
    TreeNode* node=root;
    while(node){
        if(node->left){
            TreeNode* pre=node->left;
            while(pre->right) pre=pre->right;
            pre->right=node->right;
            node->right=node->left;
            node->left=nullptr;
        }
        node=node->right;
    }
}

题目 17:左右子树交换(镜像)

与翻转二叉树一致

题目 18:子树判断

复制代码
bool isSubtree(TreeNode* s, TreeNode* t) {
    if(!s) return false;
    return isSameTree(s,t) || isSubtree(s->left,t) || isSubtree(s->right,t);
}

bool isSameTree(TreeNode* a, TreeNode* b){
    if(!a && !b) return true;
    if(!a || !b) return false;
    if(a->val != b->val) return false;
    return isSameTree(a->left,b->left) && isSameTree(a->right,b->right);
}

题目 19:统计二叉树节点数

复制代码
int countNodes(TreeNode* root) {
    if(!root) return 0;
    return 1+countNodes(root->left)+countNodes(root->right);
}

题目 20:最大深度 / 最小深度

复制代码
int maxDepth(TreeNode* root){
    if(!root) return 0;
    return 1+max(maxDepth(root->left),maxDepth(root->right));
}
int minDepth(TreeNode* root){
    if(!root) return 0;
    return 1+min(minDepth(root->left),minDepth(root->right));
}

七、总结

通过以上 20 道题,你可以看到:

  1. 建树是所有树题的基础

  2. 遍历是信息获取和递归的核心

  3. BST 的特性能大幅简化搜索类问题

  4. 路径类和动态规划类题目本质是对子树结果进行组合

  5. 特殊操作题往往是遍历 + 小技巧

相关推荐
汀、人工智能2 小时前
[特殊字符] 第27课:环形链表II
数据结构·算法·链表·数据库架构··环形链表ii
沉鱼.442 小时前
第十届题目
算法
y = xⁿ2 小时前
【LeetCode Hot100】动态规划:T70:爬楼梯 T118:杨辉三角形 T198:打家劫舍
算法·leetcode·动态规划
Liangwei Lin2 小时前
洛谷 P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins
数据结构·算法
汀、人工智能2 小时前
02 - 变量与数据类型
数据结构·算法·链表·数据库架构··02 - 变量与数据类型
hello!树2 小时前
函数极限的概念和性质
算法
人道领域2 小时前
【LeetCode 刷题日】19.删除链表的倒数第n个节点
算法·leetcode·链表
楼田莉子2 小时前
同步/异步日志系统:日志的工程意义及其实现思想
linux·服务器·开发语言·数据结构·c++
小白zlm2 小时前
连续系统-离散系统的转换
算法·嵌入式·电机控制·pmsm