迭代
/**
* 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 {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
while(root!=NULL&&(root->val<low||root->val>high)){
if(root->val<low){
root=root->right;
}else if(root->val>high){
root=root->left;
}
}
if(root==NULL) return root;
TreeNode* node=root;
while(node->left!=NULL){
if(node->left->val<low){
node->left=node->left->right;
}else{
node=node->left;
}
}
node=root;
while(node->right!=NULL){
if(node->right->val>high){
node->right=node->right->left;
}else{
node=node->right;
}
}
return root;
}
};
这题要注意的就是树的根节点可能会变,并且由于搜索树的左节点小于节点,右节点大于节点,所以并不能在修建过程中,遇到左节点小于low或右节点大于high就直接将以左节点或右节点为根节点的子搜索树全部删除。左节点小于节点,右节点大于节点,意味着当节点小于low时,节点的左节点及以下节点都小于low,而又节点及以下则有可能大于low,大于high的节点同理。所以修剪的原理就是首先找到落在区间内的root,这一步没有坑。然后从root开始向左右修建,遇到小于low的左节点,就将左节点令为原左节点的右节点,遇到大于high的右节点,就将右节点令为原右节点的左节点。
递归
/**
* 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 {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root==NULL) return root;
if(root->val>high) return trimBST(root->left,low,high);
if(root->val<low) return trimBST(root->right,low,high);
root->left=trimBST(root->left,low,high);
root->right=trimBST(root->right,low,high);
return root;
}
};
递归也是一样的原理,先找到落在区间内的root,再向左右节点开始修剪,修剪原理也相同。
/**
* 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 {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
queue<pair<int,int>>ranges;
queue<TreeNode*>nodes;
ranges.push({0,nums.size()-1});
nodes.push(new TreeNode());
TreeNode* root=nodes.front();
while(!ranges.empty()){
pair<int,int>rg=ranges.front();
ranges.pop();
TreeNode* node=nodes.front();
nodes.pop();
int tmp=(rg.second+rg.first)/2;
node->val=nums[tmp];
if(tmp!=rg.first){
ranges.push({rg.first,tmp-1});
node->left=new TreeNode();
nodes.push(node->left);
}
if(tmp!=rg.second){
ranges.push({tmp+1,rg.second});
node->right=new TreeNode();
nodes.push(node->right);
}
}
return root;
}
};
这题的关键在于要使搜索树为平衡二叉树,也就是要使树中所有节点的左侧与右侧的节点数量尽量相等。所以再构建树的过程中,不难简单的取数组的两端,而是取数组的中间元素,这就要求我们不断对数组进行分割,直到只剩一个元素。笔者采用两个队列,一个队列存放分割后的区间两端索引,一个存放节点地址。在取出一个区间与节点后,将区间的中间值赋给节点,以中间值的索引为分界,对数组进行分割,加入队列,循环往复。
/**
* 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 {
public:
TreeNode* convertBST(TreeNode* root) {
if(root==NULL) return root;
stack<TreeNode*>s;
s.push(root);
int sum=0;
while(!s.empty()){
TreeNode* node=s.top();
s.pop();
if(node!=NULL){
if(node->left!=NULL) s.push(node->left);
s.push(node);
s.push(NULL);
if(node->right!=NULL) s.push(node->right);
}else{
node=s.top();
s.pop();
sum+=node->val;
node->val=sum;
}
}
return root;
}
};
这题比较简单,只要将普通的左中右中序遍历反过来变为右中左中序遍历,再加一个求和的功能即可,要实现右中左,只需调换压入左节点与右节点的顺序即可。