这里写目录标题
669. 修剪二叉搜索树(https://leetcode.cn/problems/trim-a-binary-search-tree/submissions/432021110/)
一。思路
直接递归,出问题
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == nullptr || root->val < low || root->val > high) return nullptr;
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
};
然而在[1,3]区间要把0的右子树考虑上
二。递归
1.确定递归函数的参数以及返回值
TreeNode* trimBST(TreeNode* root, int low, int high)
2.确定终止条件:修剪的操作并不是在终止条件上进行的,所以就是遇到空节点返回就可以了
if (root == nullptr ) return nullptr;
3.确定单层递归的逻辑:如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。所以要创建一个节点为符合区间的点
找到符合区间的点很重要,递归找
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;
}
完整代码
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;
}
};
三。迭代循环处理左子树小于low的和右子树大于high的
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high)
{
if(root==nullptr)return nullptr;
//把头节点放在区间内
while(root!=nullptr&&(root->val<low||root->val>high))
{
if(root->val<low)root=root->right;//小于向右zou
else root=root->left;//大于向左走
}
TreeNode* cur=root;
//root处于区间内时,处理左孩子元素小于low的
while(cur!=nullptr)//循环一直去掉
{
while(cur->left&&cur->left->val<low)
{
cur->left=cur->left->right;//左孩子小于low那么去掉左孩子的左孩子
}
cur=cur->left;
}
//处理右孩子大于high的值
cur=root;
while(cur!=nullptr)
{
while(cur->right&&cur->right->val>high)
{
cur->right=cur->right->left;
}
cur=cur->right;
}
return root;
}
};
108. 将有序数组转换为二叉搜索树(https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/)
一。思路:与654最大二叉树类似: 取数组的中间值作为根节点,分割数组
二。递归
1.确定递归函数的参数以及返回值
TreeNode* traversal(vector<int>& nums, int left, int right)
2.确定终止条件
if(left>=right)return nullptr;
3.确定单层递归的逻辑
int index=(right+left)/2;//分割点
TreeNode* node =new TreeNode(nums[index]);
4.完整代码
class Solution {
public:
TreeNode* traversal(vector<int>& nums, int left, int right)
{
if(left>=right)return nullptr;
int index=(right+left)/2;//分割点
TreeNode* node =new TreeNode(nums[index]);
node->left=traversal(nums,left,index);
node->right=traversal(nums,index+1,right);
return node;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
return traversal(nums,0,nums.size());
}
};
5.出错的地方
1.递归时对于数组左右值拿捏不准,最开始写的错误为
错误代码
node->left=traversal(nums,left,left+index);
node->right=traversal(nums,left+index+1,right);
2.调用traversal函数时,数组值代错
错误代码
return traversal(nums,0,nums.size()-1);//不用减1
三。迭代:用三个队列模拟,一个队列放遍历的节点,一个放左区间下标,一个放右区间下标
538. 把二叉搜索树转换为累加树
一。思路:与二叉搜索树的最小绝对差相似,用到双指针
从最右下的8开始,8还是8,7=8+7,6=8+7+6+5;4=8+7+6+5+
1.给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
将题目转换成:一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],[13+5+2,13,13]所以遍历顺序与中序相反
二。递归
1.确定递归函数的参数以及返回值
定义一个全局变量pre,用来保存cur节点的前一个节点的数值,定义为int型就可以了。
代码如下:
TreeNode* pre=nullptr;
TreeNode* convertBST(TreeNode* root)
2.确定终止条件:遇空终止
if(root==nullptr)return nullptr;
3.确定单层递归的逻辑:右中左来遍历,中节点的处理逻辑就是让cur的数值加上前一个节点的数值
if(pre!=nullptr)//处理中
{
root->val+=pre->val;
}
pre=root;
4.完整代码
class Solution {
public://反中序遍历
TreeNode* pre=nullptr;
TreeNode* convertBST(TreeNode* root) {
if(root==nullptr)return nullptr;
convertBST(root->right);//先右
if(pre!=nullptr)//处理中
{
root->val+=pre->val;
}
pre=root;
convertBST(root->left);//再左
return root;
}
};
三。迭代:反中序遍历
中序遍历在栈里面是右中左,本题要反中序遍历,所以进栈的顺序是左中右
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
TreeNode* pre=nullptr;
if(root==nullptr)return nullptr;
stack<TreeNode*>input;
input.push(root);
while(!input.empty())
{
TreeNode* cur=input.top();
if(cur!=nullptr)
{
input.pop();
if(cur->left)input.push(cur->left);
input.push(cur);
input.push(nullptr);
if(cur->right)input.push(cur->right);
}
else{
input.pop();
cur=input.top();
input.pop();
if(pre!=nullptr)
{
cur->val+=pre->val;
}
pre=cur;
}
}
return root;
}
};