二叉搜索树第一期
01 二叉搜索树中第 K 小的元素
给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。
直接的思路就是升序排序,然后寻找第 k 个元素即可。BST 的中序遍历就是升序排序的结果。
// 记录结果int res = 0;// 记录当前元素的排名int rank = 0;void traverse(TreeNode* root, int k) {if (root == nullptr)return;traverse(root->left, k);// 中序遍历代码位置rank++;if (k == rank) {res = root->val;return;}traverse(root->right, k);}int kthSmallest(TreeNdoe* root, int k) {traverse(root, k);return res;}
但是这个解法不是最高效的。
按照我们刚才说的方法,利用「BST 中序遍历就是升序排序的结果」这个性质,每次寻找第 k 小的元素都要中序遍历一次,最坏的时间复杂度是 O(N),N 是 BST 的节点个数。
如果想要达到对数级复杂度,关键在于每个节点知道他自己排第几。
02 把二叉搜索树转换为累加树

如图所示,比如图中的节点 5,转成累加树的话,比 5 大的节点有 6, 7, 8,加上 5 本身,所以累加树上的这个节点的值应该是 26。
一个简单的思路就是计算大于等于当前值的所有元素之和,那么每个节点都去计算右子树的和不就行了吗?
这是不行的。对于一个节点来说,右子树都是比它大的元素,但是它的父节点也可能是比它大的元素。其实,可以将 BST 降序打印即可。维护一个外部变量 sum,然后把 sum 赋值给 BST 中的每一个节点。
int sum = 0;void traverse(TreeNode* root) {if (root == nullptr)return;traverse(root->right);// 维护累加树sum += root->val;// 将 BST 转换为累加树root->val = sum;traverse(root->left);}TreeNode* convertBST(TreeNode* root) {traverse(root);}
BST 相关的题目,要么利用 BST 左小右大的特性提升算法效率,要么利用中序遍历的特性满足题目要求。
