代码随想录算法训练营第21天 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树
文章目录
669. 修剪二叉搜索树
解题思路
通过递归三部曲进行分析:
- 确定递归函数的参数和返回值:通过递归函数的返回值来删除节点,因为是修剪操作,所以不需要返回值也能够完成
- 确定终止条件:遇到空节点返回即可
- 确定单层递归逻辑:若 root 的元素小于左边界 low 的数值,那么就递归右子树,返回右子树符合条件的头节点;若 root 的元素大于右边界 high 的数值,就递归左子树,返回左子树符合条件的头节点,接下来将下一层递归处理左子树的结果赋值给 root->left 、处理右子树的结果赋值给 root->right ,最后返回 root。
代码实现
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == nullptr)
return nullptr;
if (root->val < low) {
TreeNode* right = trimBST(root->right, low, high);
return right;
}
if (root->val > high) {
TreeNode* left = trimBST(root->left, low, high);
return left;
}
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
};
题目总结
本题还可以用迭代法来解决,剪枝操作分为三步:1.将 root 移动到 [low,high] 范围内,2.剪枝左子树,3.剪枝右子树。
108.将有序数组转换为二叉搜索树
解题思路
基于有序数组构造二叉搜索树,寻找分割点比较容易,分割点就是数组中间位置的节点。若数组长度为偶数,中间节点有两个时,选择不同的节点会构成不同的平衡二叉搜索树。
代码实现
class Solution {
public:
TreeNode* traversal(vector<int>& nums, int left, int right) {
if (left > right)
return nullptr;
int mid = left + (right - left) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = traversal(nums, left, mid - 1);
root->right = traversal(nums, mid + 1, right);
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root = traversal(nums, 0, nums.size() - 1);
return root;
}
};
题目总结
定义的区间为左闭右闭,在调用 traversal 函数时传入的 left 和 right 是 0 和 nums.size()-1。
538.把二叉搜索树转换为累加树
解题思路
从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了。本题依然需要一个pre指针记录当前遍历节点cur的前一个节点,这样才方便做累加。
代码实现
class Solution {
public:
int pre = 0;
void traversal(TreeNode* cur) {
if (cur == nullptr)
return;
traversal(cur->right);
cur->val += pre;
pre = cur->val;
traversal(cur->left);
}
TreeNode* convertBST(TreeNode* root) {
pre = 0;
traversal(root);
return root;
}
};
题目总结
注意右中左遍历二叉树,中节点的处理逻辑就是让 cur 的数值加上前一个节点的数值。