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)
八、这题的本质
后序遍历 + 分两种路径计算
-
一种:更新答案(左右都要)
-
一种:返回父节点(只能选一边)