【leetcode hot 100】依旧二叉树

1.

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 {
private:
    int count = 0;  // 当前访问的节点计数
    int result = 0; // 存储第 k 小的值
    
    void inorder(TreeNode* root, int k) {
        if (!root) return;
        
        // 左子树
        inorder(root->left, k);
        
        // 访问当前节点
        count++;
        if (count == k) {
            result = root->val;
            return;
        }
        
        // 右子树
        inorder(root->right, k);
    }
    
public:
    int kthSmallest(TreeNode* root, int k) {
        inorder(root, k);
        return result;
    }
};

二叉搜索树第 k 小元素:中序遍历一招解决

这道题是 BST(搜索树)里非常经典的一题,本质就一句话:

利用 BST 的"中序遍历有序"性质


一、题目本质

在 BST 中找第 k 小的数


二、核心性质(关键)

BST 的中序遍历 = 升序序列

复制代码
Left → Root → Right

例如:

复制代码
    5
   / \
  3   7
 / \
2   4

中序遍历:

复制代码
2 → 3 → 4 → 5 → 7

第 k 小 = 第 k 个访问到的节点


三、代码在做什么

全局变量

复制代码
int count = 0;
int result = 0;

count:记录访问到第几个节点

result:记录答案


中序遍历

复制代码
void inorder(TreeNode* root, int k)

四、递归核心逻辑

复制代码
inorder(root->left, k);

先访问更小的节点


复制代码
count++;
if (count == k) {
    result = root->val;
    return;
}

找到第 k 个,直接记录


复制代码
inorder(root->right, k);

再访问更大的节点


五、执行过程(必须理解)

假设:

复制代码
k = 3

中序序列:

复制代码
2 → 3 → 4 → 5 → 7

过程:

  • 访问 2 → count=1

  • 访问 3 → count=2

  • 访问 4 → count=3 ✔

返回 4


七、时间和空间复杂度

时间复杂度:

O(k) ~ O(n)

最好情况只走到第 k 个

空间复杂度:

O(h)


八、进阶解法

如果是"动态 BST"(频繁插入删除):

可以用:

  • 节点记录子树大小(Order Statistic Tree)

这样可以:

O(log n) 找第 k 小


九、这一题的本质

把"第 k 小"转化为"中序第 k 个访问节点"


十、一句话总结

👉 BST 第 k 小 = 中序遍历第 k 次访问

2.

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 {
private:
    int max_sum;
    int dfs(TreeNode* node)
    {
        if(!node)
        {
            return 0;
        }
        int left=max(0,dfs(node->left));
        int right=max(0,dfs(node->right));
        int current=node->val+left+right;
        max_sum=max(max_sum,current);
        return node->val+max(left,right);
    }
    
public:
    int maxPathSum(TreeNode* root) {
        max_sum = INT_MIN;
        dfs(root);
        return max_sum;
    }
};

二叉树最大路径和详解:最难树题之一,彻底讲透

这道题是树里含金量非常高的一题,很多人会卡在两个点:

  • 为什么要 max(0, ...)

  • 为什么返回值和更新答案不一样

你这份代码已经是最优标准解法,我们把它彻底拆开。


一、题目本质

找一条路径,使得路径和最大

注意:

  • 路径可以从任意节点开始

  • 路径可以在任意节点结束

  • 不一定经过根节点


二、核心思想(最关键一句话)

每个节点都可以作为"路径的拐点"

路径形态是:

复制代码
左子树 → 当前节点 → 右子树

三、代码在做什么

复制代码
int dfs(TreeNode* node)

返回:从当前节点向下走的最大路径和(单边)

同时:

在过程中更新全局最大值 max_sum


四、递归核心拆解(重点)

1. 终止条件

复制代码
if (!node) return 0;

2. 计算左右子树

复制代码
int left = max(0, dfs(node->left));
int right = max(0, dfs(node->right));

关键点来了:

  • 如果子树是负数 → 不要(当作 0)

  • 因为负数只会拖累路径


3. 更新最大路径

复制代码
int current = node->val + left + right;
max_sum = max(max_sum, current);

这是"完整路径":

复制代码
左 + 当前 + 右

4. 返回值(非常关键)

复制代码
return node->val + max(left, right);

只能选一边!

因为:

往上走的路径不能分叉


五、举个例子(必须理解)

复制代码
      -10
      /  \
     9   20
        /  \
       15   7

分析:

  • 节点 20:15 + 20 + 7 = 42 ✔

  • 这是最大路径

注意:路径没有经过根节点!


六、两个"最大值"的区别

1. max_sum

全局最大路径(可以左右都选)


2. dfs 返回值

只能选一边,用于向上传递


这是这题最核心的区别!


七、时间和空间复杂度

时间复杂度:

O(n)

空间复杂度:

O(h)


八、这题的本质

后序遍历 + 分两种路径计算

  • 一种:更新答案(左右都要)

  • 一种:返回父节点(只能选一边)

相关推荐
小羊没烦恼!12 分钟前
Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?
java·开发语言·windows·算法·c#
ysu_03141 小时前
08-二叉树遍历:四种方式详解
c语言·数据结构·算法·leetcode
咸鱼老弟1 小时前
Speculative Decoding(投机采样):大模型"先猜后验",生成速度翻倍
前端·算法·ai编程
荆棘鸟智能1 小时前
AI算法持续学习与迭代怎么做?从数据闭环到灰度发布的MLOps工程实践
人工智能·算法·架构·边缘计算
Lyyaoo.1 小时前
【二分查找】【中等】搜索二维矩阵/排序数组的第一位和最后位置/搜索旋转排序数组/旋转排序数组中的最小值
java·数据结构·算法
土司大王1 小时前
LeetCode hot100——153.寻找旋转排序数组中的最小值:Java 二分模板与 O(log n) 分析
java·算法·leetcode
光电的一只菜鸡1 小时前
isp中关于锐化对图像清晰度的影响
算法
土司大王2 小时前
LeetCode hot100——4.寻找两个正序数组的中位数:Java 二分第K小 递归裁剪
java·算法·leetcode
薛定e的猫咪2 小时前
(ICML2024)QSM:基于 Q 函数梯度对齐分数场的扩散模型离策略强化学习
人工智能·深度学习·算法