文章目录
- 0. Leetcode [700. 二叉搜索树中的搜索](https://leetcode.cn/problems/search-in-a-binary-search-tree/)
- 1. Leetcode [230. 二叉搜索树中第K小的元素](https://leetcode.cn/problems/kth-smallest-element-in-a-bst/)
- 2. Leetcode [108. 将有序数组转换为二叉搜索树](https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/)
- 3. Leetcode [1382. 将二叉搜索树变平衡](https://leetcode.cn/problems/balance-a-binary-search-tree/)
- 总结
0. Leetcode 700. 二叉搜索树中的搜索
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
分析与解答
前序遍历,若 rootVal == target
,返回根节点;若 rootval < target
则搜索右子树;若 rootval > target
则搜索左子树:
/**
* 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 {
TreeNode* result;
public:
void dfs(TreeNode* root, int val) {
if (root == nullptr) {
return;
}
if (root->val == val) {
result = root;
}
if (root->val > val) {
dfs(root->left, val);
}
if (root->val < val) {
dfs(root->right, val);
}
}
TreeNode* searchBST(TreeNode* root, int val) {
dfs(root, val);
return result;
}
};
1. Leetcode 230. 二叉搜索树中第K小的元素
给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。
分析与解答
可以中序遍历后返回第 k 个位置的值。
此处由于第
k
k
k 小的元素,即第
s
i
z
e
−
k
+
1
size - k + 1
size−k+1 大的元素:
/**
* 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 {
vector<int> result;
int res;
public:
void dfs(TreeNode* root, int k) {
if (root == nullptr) {
return;
}
dfs(root->left, k);
if (result.size() == k - 1) { // 搜索到第 size - k + 1 个元素
res = root->val;
}
result.push_back(k);
dfs(root->right, k);
}
int kthSmallest(TreeNode* root, int k) {
dfs(root, k);
return res;
}
};
2. Leetcode 108. 将有序数组转换为二叉搜索树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
分析与解答
若要构成平衡二叉树,即每次取数组中间值作为当前的新插入节点,即可保证构造完成后左右子树深度差不超过 1 1 1:
/**
* 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 {
TreeNode* root;
public:
void balanceTree(vector<int>& nums, int l, int r, TreeNode* preNode) {
if (l > r) { // 构造完成
return;
}
int mid = (l + r) / 2;
TreeNode* curNode = new TreeNode(nums[mid]); // 构造当前节点
if (preNode == nullptr) { // 根节点
root = curNode;
} else {
if (nums[mid] < preNode->val) { // 将当前节点插入上一节点的左子树
preNode->left = curNode;
} else { // 将当前节点插入上一节点的右子树
preNode->right = curNode;
}
}
balanceTree(nums, l, mid - 1, curNode); // 构造左子树
balanceTree(nums, mid + 1, r, curNode); // 构造右子树
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
// 每个节点左子树与右子树差不超过 1
root = nullptr;
balanceTree(nums, 0, nums.size() - 1, root);
return root;
}
};
3. Leetcode 1382. 将二叉搜索树变平衡
给你一棵二叉搜索树,请你返回一棵 平衡后 的二叉搜索树,新生成的树应该与原来的树有着相同的节点值。如果有多种构造方法,请你返回任意一种。
如果一棵二叉搜索树中,每个节点的两棵子树高度差不超过 1 ,我们就称这棵二叉搜索树是 平衡的 。
分析与解答
中序遍历构造排序好的数组后,根据上一题方法构造平衡二叉树即可:
/**
* 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 {
vector<int> nums;
TreeNode* result;
public:
void dfs(TreeNode* root) {
if (root == nullptr) {
return;
}
dfs(root->left);
nums.push_back(root->val);
dfs(root->right);
}
void bulidTree(int l, int r, TreeNode* preNode) {
if (l > r) {
return;
}
int mid = (l + r) / 2;
TreeNode* curNode = new TreeNode(nums[mid]);
if (preNode == nullptr) {
result = curNode;
} else {
if (nums[mid] < preNode->val) {
preNode->left = curNode;
} else {
preNode->right = curNode;
}
}
bulidTree(l, mid - 1, curNode);
bulidTree(mid + 1, r, curNode);
}
TreeNode* balanceBST(TreeNode* root) {
nums.clear();
result = nullptr;
dfs(root);
bulidTree(0, nums.size() - 1, result);
return result;
}
};
总结
二叉搜索树与树使用的算法差异不大,在需要降低时间复杂度时牢牢把握二叉搜索树是有序的这一特性即可。