修剪二叉搜索树 leetcode 659
解法一:递归
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root==nullptr) return root;
if(root->val<low) return trimBST(root->right,low,high);
if(root->val>high) return trimBST(root->left,low,high);
root->left=trimBST(root->left,low,high);
root->right=trimBST(root->right,low,high);
return root;
}
};
当前节点的val小于low的话,节点左子树肯定都要删,因此我们只需要修剪右子树。此时,调用return trimBST(root->right,low,high);将右子树的修剪结果返回,并且不保留当前节点(因为它的值不在范围内)。
大于high的话,同理我们只需要修剪左子树,返回左子树的修剪结果,并且不保留当前节点。
解法二:迭代
首先处理头节点,让新的头节点处于区间之内,此时头节点的左孩子一定是处于区间只能或在区间左边,只需要处理在区间左边的情况,也就是删掉左孩子本身以及左孩子的左子树。头节点的右孩子同理。
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root==nullptr) return root;
while(root!=nullptr&&(root->val<low||root->val>high)){
if(root->val<low) root=root->right;
else root=root->left;
}
TreeNode* cur=root;
while(cur){
while(cur->left&&cur->left->val<low){
cur->left=cur->left->right;
}
cur=cur->left;
}
cur=root;
while(cur){
while(cur->right&&cur->right->val>high){
cur->right=cur->right->left;
}
cur=cur->right;
}
return root;
}
};
出现的错误
while(cur->left&&cur->left->val<low){
cur->left=cur->left->right;
}
这是删掉左孩子以及左孩子的左子树操作,要使用while循环删除,使用if的话只能闪删一次,如果左孩子的右孩子(会作为下一次迭代的左孩子)的val也小于low的话就删不掉了。
将有序数组转换为平衡二叉搜索树 leetcode 108
解法一:递归
class Solution {
public:
TreeNode* traversal(vector<int>& nums,int left,int right){
if(left>right) return nullptr;
int mid=(right-left)/2+left;
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) {
return traversal(nums,0,nums.size()-1);
}
};
总结
1.平衡二叉搜索树左右子树的绝对值不超过1,所以可以把数组从中间分开,中间的数作为根节点,左右两边分别构造左子树和右子树。
2.计算中间位置mid=left+(right-left)/2;是为了避免整数溢出。
解法二:迭代
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
if(nums.size()==0) return nullptr;
queue<TreeNode*> que;
queue<int> leftque;
queue<int> rightque;
TreeNode* root=new TreeNode(0);
que.push(root);
leftque.push(0);
rightque.push(nums.size()-1);
while(!que.empty()){
TreeNode* cur=que.front();
que.pop();
int left=leftque.front(); leftque.pop();
int right=rightque.front(); rightque.pop();
int mid=left+(right-left)/2;
cur->val=nums[mid];
if(left<=mid-1){
cur->left=new TreeNode(0);
que.push(cur->left);
leftque.push(left);
rightque.push(mid-1);
}
if(right>mid){
cur->right=new TreeNode(0);
que.push(cur->right);
leftque.push(mid+1);
rightque.push(right);
}
}
return root;
}
};
不断分隔区间,所有节点初始化为0,在 cur->val=nums[mid];进行赋值。
把二叉搜索树转换为累加树 leetcode 538
解法一:递归双指针(右中左)
累加要从最大值开始累加,所以遍历顺序为右中左。
class Solution {
public:
int pre=0;
void traversal(TreeNode* cur){
if(!cur) return;
traversal(cur->right);
cur->val+=pre;
pre=cur->val;
traversal(cur->left);
return;
}
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
};
解法二:迭代
class Solution {
public:
int pre=0;
void traversal(TreeNode* cur){
stack<TreeNode*> st;
while(cur||!st.empty()){
if(cur){
st.push(cur);
cur=cur->right;
}else{
cur=st.top();
st.pop();
cur->val+=pre;
pre=cur->val;
cur=cur->left;
}
}
}
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
};
while循环条件中的cur不为空是为了先遍历到树的最右下角,栈不为空是为了弹出栈中元素进行累加赋值。