669. 修剪二叉搜索树
题目链接:669. 修剪二叉搜索树
非递归法
给出上下限,对二叉搜索树进行修剪。
对于下限,从根节点开始遍历,大于下限就前往左子树,等于下限就记录位置,小于下限就前往右子树直到大于等于下限,接回为记录位置的右节点;若根节点即小于下限,则根节点的右子树中大于下限的第一个节点为新的根节点。
对于上限,与下限逻辑相反。
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
TreeNode* cur = root;
while(root->val < low || root->val > high){
// 根节点小于下限
if(root->val < low){
cur = root;
while(cur->val < low){
if(cur->right) cur = cur->right;
else return NULL;
}
root = cur;
}
// 根节点大于上限
else if(root->val > high){
cur = root;
while(cur->val > high){
if(cur->left) cur = cur->left;
else return NULL;
}
root = cur;
}
}
// 找下限
while(1){
cur = root;
TreeNode* pre = cur;
while(cur != NULL && cur->val >= low){
pre = cur;
cur = cur->left;
}
while(cur != NULL && cur->val < low){
cur = cur->right;
}
pre->left = cur;
// 验证最小值
cur = root;
while(cur->left){
cur = cur->left;
}
if(cur->val >= low) break;
}
// 找上限
while(1){
cur = root;
TreeNode* pre = cur;
while(cur != NULL && cur->val <= high){
pre = cur;
cur = cur->right;
}
while(cur != NULL && cur->val > high){
cur = cur->left;
}
pre->right = cur;
// 验证最大值
cur = root;
while(cur->right){
cur = cur->right;
}
if(cur->val <= high) break;
}
return root;
}
};
我写了好长,看了下解析发现是绕圈子了;简单理清思路,应该是先把新根节点确定了,然后再左右确定上下界;
递归法
按照逻辑分析写的代码,有点繁琐,再考虑下递归法:
(1)参数:当前节点,上下界;返回值:节点;
(2)终止条件:节点为空;
(3)中间逻辑:若当前节点值大于上限,递归返回左孩子;若小于下限,递归返回右孩子;若在界内,递归左右孩子;
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if(root == NULL) return NULL;
if(root->val < low){
root = trimBST(root->right, low, high);
}
else if(root->val > high){
root = trimBST(root->left, low, high);
}
else{
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
}
return root;
}
};
递归法代码不要简单太多啊!
108.将有序数组转换为二叉搜索树
题目链接:108. 将有序数组转换为二叉搜索树
递归法
这次思路很清晰,直奔递归,递归很好想。为了保持二叉搜索树的平衡,在一开始建树时,就平衡地来建最为保险;从有序数组中取出中位数作为根节点,然后两边作为子树,如此递归实现全部建树。
class Solution {
public:
vector<int> value;
TreeNode* setBST(int l, int r){
if(r - l <= 0) return NULL;
int index = l + ((r - l) /2);
TreeNode* node = new TreeNode(value[index]);
node->left = setBST(l, index);
node->right = setBST(index + 1, r);
return node;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
value = nums;
return setBST(0, nums.size());
}
};
迭代法
迭代法的重点在于把该插入树中的数值找出来,我们用队列实现;
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
if(nums.size() == 0) return NULL;
TreeNode* root = new TreeNode(0);
queue<pair<int, int>> indexQue;
queue<TreeNode*> nodeQue;
indexQue.push({0, nums.size()});
nodeQue.push(root);
while(!nodeQue.empty()){
int left = indexQue.front().first;
int right = indexQue.front().second; indexQue.pop();
int mid = left + ((right - left) / 2);
TreeNode* node = nodeQue.front(); nodeQue.pop();
node->val = nums[mid];
if(left < mid){
node->left = new TreeNode(0);
nodeQue.push(node->left);
indexQue.push({left, mid});
}
if(right > mid + 1){
node->right = new TreeNode(0);
nodeQue.push(node->right);
indexQue.push({mid + 1, right});
}
}
return root;
}
};
538.把二叉搜索树转换为累加树
题目链接:538. 把二叉搜索树转换为累加树
思路
因为是大于等于当前节点值的累加,所以应当是按照中序遍历的倒序进行累加,所以可以按照右中左的顺序进行遍历;
递归法
class Solution {
public:
int sum = 0;
void traversal(TreeNode* cur){
if(cur == NULL) return;
traversal(cur->right);
sum += cur->val;
cur->val = sum;
traversal(cur->left);
}
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
};
迭代法
与中序遍历的迭代法一样。
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
if(root == NULL) return NULL;
stack<TreeNode*> st;
st.push(root);
int sum = 0;
while(!st.empty()){
TreeNode* node = st.top(); st.pop();
if(node != NULL){
if(node->left) st.push(node->left);
st.push(node);
st.push(NULL);
if(node->right) st.push(node->right);
} else {
node = st.top(); st.pop();
sum += node->val;
node->val = sum;
}
}
return root;
}
};