目录:
给你二叉搜索树的根节点 root
,同时给定最小边界low
和最大边界 high
。通过修剪二叉搜索树,使得所有节点的值在[low, high]
中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
示例 1:
!https://assets.leetcode.com/uploads/2020/09/09/trim1.jpg
输入:root = [1,0,2], low = 1, high = 2
输出:[1,null,2]
思考:比较麻烦的是找到边界节点后他的子节点还可能属于给定范围。但是如果找到了左边界,可以将其右子树用来代替当前位置。如果找到了右边界,可以将其左子树来代替当前节点。
单层递归逻辑:如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == NULL) return root;
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;
}
};
迭代法
在剪枝的时候,可以分为三步:
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (!root) return nullptr;
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 != nullptr) {
while(cur->left && cur->left->val < low) {
cur->left = cur->left->right;
}
cur = cur->left;
}
cur = root;
while (cur != nullptr) {
while(cur->right && cur->right->val > high) {
cur->right = cur->right->left;
}
cur = cur->right;
}
return root;
}
};
迭代法的思路跟我想的比较像,只需要找到第一个不在范围内的节点,然后将其左右子树返回就行。
给你一个整数数组 nums
,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
示例 1:
!https://assets.leetcode.com/uploads/2021/02/18/btree1.jpg
输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
思考:似乎可以每次都去找中间节点的索引,然后其左边为左子树,右边为右子树。
注意区间是否是左闭右开,还是左闭右闭。
在调用traversal的时候传入的left和right为什么是0和nums.size() - 1,因为定义的区间为左闭右闭。
class Solution {
public:
TreeNode* turnToBST(vector<int>& nums, int left, int right)
{
if (left > right) return NULL;
int mid = left + (right - left) / 2;
TreeNode* node = new TreeNode(nums[mid]);
node->left = turnToBST(nums, left, mid - 1);
node->right = turnToBST(nums, mid + 1, right);
return node;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root = turnToBST(nums, 0, nums.size() - 1);
return root;
}
};
迭代法太复杂了,不看。
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node
的新值等于原树中大于或等于 node.val
的值之和。
示例 1:
!https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2019/05/03/tree.png
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
思考:转换成累加数这个用一个pre指针就能搞定。然后这棵树跟之前不一样,得从右边先遍历。右中左的处理逻辑来。
class Solution {
public:
int pre;
void traversal(TreeNode* cur) {
if (cur == nullptr) return;
traversal(cur->right);
//下面的判断条件不加上也行
if (pre != 0) {
cur->val += pre;
}
pre = cur->val;
traversal(cur->left);
}
TreeNode* convertBST(TreeNode* root) {
pre = 0;
traversal(root);
return root;
}
};
迭代法处理:
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
stack<TreeNode*> st;
int pre = 0;
TreeNode* cur = root;
while(cur != NULL || !st.empty()) {
if (cur != NULL) {
st.push(cur);
cur = cur->right;
} else {
TreeNode* node = st.top();
st.pop();
node->val += pre;
pre = node->val;
cur = node->left;
}
}
return root;
}
};
看到二叉树,看到递归,想:返回值、参数是什么?终止条件是什么?单层逻辑是什么?