LeetCode 669. 修剪二叉搜索树
思路:
这道题目理解起来确实不容易,要注意的是和删除二叉搜索树的节点不同,这里要修剪的是整颗子树。而且当某个节点不符合要求的时候,不能直接把这个节点以及节点下所有的子节点全部删除,因为要考虑到并不是所有的子节点都不符合情况。比如当前节点的值低于low,需要修剪的则为当前节点和左节点的整颗子树还有部分不符合要求的右子树的节点。那么需要返回的节点则是剩下那些符合要求的节点。
如何找到剩下那些符合要求的节点呢?可以用递归的方法,如果root->val低于low,则查找root右边的节点,如此递归查找下去直到找到符合条件的值或者null,并把结果返回到root的子节点,最后再把root返回即可。
代码:
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == nullptr)
return nullptr;
// 当前节点大于high,递归左子树寻找小于high的节点
// 并将节点返回至上一个节点
if (root->val > high)
{
TreeNode* left = root->left;
return trimBST(left, low, high);
}
// 当前节点小于low,递归右子树寻找大于low的节点
// 并将节点返回至上一个节点
if (root->val < low)
{
TreeNode* right = root->right;
return trimBST(right, low, high);
}
// 当前节点如果在范围内,更新left和right节点
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
};
LeetCode 108. 将有序数组转换为二叉搜索树
思路:
这道题目和105. 从前序与中序遍历序列构造二叉树以及654. 最大二叉树类似,都是以某种规律构造一个二叉树,而这题的难度要比前两题的简单得多,重点同样还是寻找分割点,然后分割数组。我们知道二叉搜索树中序遍历后是一个有序数组,所以相应地根据中序遍历的顺序,只要找到中点就可以确定左右节点了,那么这道题的切割方式就是用中点切割。
寻找有序数组的中点很简单,只需要把头尾指针加起来除以二就可以了。剩余步骤和其他构造二叉树的题目类似,都是确认好左数组的头尾指针,以及右数组的头尾指针,然后分别传递给递归函数用于返回左子树和右子树的头节点。注意递归结束的条件为左指针大于右指针,不能是大于等于,因为左指针等于右指针代表数组里的元素数量为1。
代码:
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root = traversal(nums, 0, nums.size() - 1);
return root;
}
TreeNode* traversal(vector<int>& nums, int left, int right)
{
if (left > right)
return nullptr;
int middle = (left + right) / 2;
TreeNode* root = new TreeNode(nums[middle]);
root->left = traversal(nums, left, middle - 1);
root->right = traversal(nums, middle + 1, right);
return root;
}
};
LeetCode 538. 把二叉搜索树转换为累加树
思路:
累加树需要用到前一个节点的值,然后把前一个节点的值累加到当前节点上,以此类推,所以本题需要用到双指针,然后自底向上中序遍历,其做法和530. 二叉搜索树的最小绝对差还有501. 二叉搜索树中的众数是一样的,都是定义一个prev节点储存前一个节点,然后中序遍历操作节点的值。
代码:
class Solution {
public:
TreeNode* prev;
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
void traversal(TreeNode* root)
{
if (root == nullptr)
return;
traversal(root->right);
if (prev != nullptr)
root->val += prev->val;
prev = root;
traversal(root->left);
}
};