代码随想录Day23 | ● 669. 修剪二叉搜索树 ● 669. 修剪二叉搜索树 ● 669. 修剪二叉搜索树
修剪二叉搜索树
文档讲解:代码随想录
视频讲解: 你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树
状态
主要考虑的情况是当删除节点时,如果当前节点的值小于low,那么说明左子树所有节点都是小于Low的,而对于右子树需要一直递归直到当前节点的值大于等于val。而对于大于high的节点,就说明右子树所有节点都是大于high的,而对于左子树需要一直递归直到当前节点的值小于等于val。
- 当当前节点为空,就返回
- 单层递归
//对中节点的情况处理,如果不满足就需要更新
if(root->val < low)
{
//向右子树寻找第一个大于等于low的节点
TreeNode* left = find(root->right,low,high);
return left;
}
if(root->val > high)
{
//向左子树寻找第一个小于等于High的节点
TreeNode* right = find(root->left,low,high);
return right;
}
//正确中节点的左子树
root->left = find(root->left,low,high);
//正确中节点的右子树
root->right = find(root->right,low,high);
具体代码
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root == nullptr) return root;
//中节点
if(root->val < low)
{
TreeNode* left = trimBST(root->right,low,high);
return left;
}
if(root->val > high)
{
TreeNode* right = trimBST(root->left,low,high);
return right;
}
//向下节点递归
root->left = trimBST(root->left,low,high);
root->right = trimBST(root->right,low,high);
return root;
}
};
将有序数组转换为二叉搜索树
文档讲解:代码随想录
视频讲解: 构造平衡二叉搜索树!| LeetCode:108.将有序数组转换为二叉搜索树
状态
本题和构造二叉树的方法类似,在数组中找到根节点位置,然后以根节点分隔数组,递归调用函数,并使用根节点的左指针和右指针接受返回值。
由于已经是升序数组了,所以以数组的mid位置的数为根节点,左边的构成左子树,右边的构成右子树。左右两个数组同样升序,那么可以递归这样建树,递归函数每次传入数组的左右边界,并用上一个节点的左和右值接受子数组的返回节点。
当左边界大于等于右边界时,就返回空节点。
class Solution {
public:
TreeNode* getArray(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 = getArray(nums,left,mid-1);
root->right = getArray(nums,mid+1,right);
return root;
}
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
int left = 0;
int right = nums.size()-1;
return getArray(nums, left ,right);
}
};
把二叉搜索树转换为累加树
文档讲解:代码随想录
视频讲解: 普大喜奔!二叉树章节已全部更完啦!| LeetCode:538.把二叉搜索树转换为累加树
状态
二叉搜索树,大于等于相当于该节点的值等于右边所有节点值,显然中序遍历,节点值就是从节点开始向右的所有值。
所以如果先递归到最右的节点,进行一个右中左方式的遍历,我们定义一个全局变量,用来记录当前已经遍历的节点的和,那么下一个遍历的节点之和就是这个和加上其本身
class Solution {
private:
int sum = 0;
public:
TreeNode* convertBST(TreeNode* root) {
if(root == nullptr) return nullptr;
convertBST(root->right);
sum += root->val;
root->val = sum;
convertBST(root->left);
return root;
}
};
使用哪种遍历顺序
中节点的位置一般为处理结果的位置,左右节点一般只用来递归调用
- 对于二叉树的构造,那么一般使用前序,通过寻找中节点在数组的位置,然后分割数组,递归。要注意区间闭合的不变性
TreeNode* get(vector<int>& nums, int left, int right)
{
//中节点
root = new mid;
//
root->left = get(nums,left,mid-1);
root->right = get(nums,mid+1,right);
}
- 对于二叉搜索树,要考虑中序,因为二叉搜索树是有序的,左子树是小于中节点的,右子树是大于中节点的。利用中序可以很好的划分左右节点的搜寻路径
- 对于一些普通二叉树的处理,一般都是用后序,其实就是需要使用递归函数的返回值做计算,但也有例外比如求二叉树的所有路径,由于需要父节点去指向子节点。但使用前序遍历时,需要注意回溯问题。因为每个父节点可能会有两条路径。
还是得多复习复习,刷了这几天感觉头有点昏昏的,还没形成体系。