669. 修剪二叉搜索树
对于该题,对结点中的判断逻辑,如果为NULL,就返回NULL, 如果 < low, 则再次去遍历 该节点的右子树,因为右子树中可能会有符合条件的值, 对处理过的右子树进行返回, 同样的,如果 > high, 则再次去遍历 该结点的左子树,因为左子树可能会有符合条件的值, 对处理 过的左子树进行返回。
然后递归时,让结点的左子树 去 接住 处理过的左子树, 右子树 去接住处理过的右子树,然后进行返回。
再这里有个问题时,对于删除结点的内存的释放,这块还存在问题。
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == NULL) return NULL;
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;
}
};
108.将有序数组转换为二叉搜索树
关于如何利用数组去构造二叉树的整体思路:
先选取一个中间的结点,将这个数组分为左区间 和 右区间,然后递归遍历左区间,然后构成了左子树,递归去遍历右区间,去构成了右子树。
对于本题而言,选取中间结点的时候一定要选取中间位置的结点,只有这样,才能保证它的左区间的结点数量和右区间的结点数量是相同的,这样构造出来的二叉树才能保证它是平衡的。将其分割后,左区间也选中间结点,再去左右分割,同样的,右区间也选中间结点,左右分割,这样就保证了它的每一层下面左右子树结点数量相同,然后根据二叉搜索树结点的性质进行构造。
当数组长度为奇数时,取中间结点,当为偶数时,取中间偏左或者偏右的结点都是可以的,只不过两者的构造顺序略有差异。
对于数组作为函数参数时,对C++ 语言而言,建议使用引用,不然会引起内存空间的重复copy,这样就会导致程序的性能很差。 其他语言就没有这个问题,自带内存回收机制。
对于数组的区间,一定要明确 是 左闭右闭呢, 还是左闭右开
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return traversal(nums, 0, nums.size() - 1);
}
// 区间为 左 闭 右 闭[]
TreeNode* traversal(vector<int>& nums, int left, int right) {
if (left > right) return NULL;
int mid = (left + right) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = traversal(nums, left, mid - 1);
root->right = traversal(nums, mid + 1, right);
return root;
}
};
538.把二叉搜索树转换为累加树
根据题目中给的顺序而言,将二叉搜索树转换为数组的话,就是从后往前累加,切换回二叉树的话,就是右中左去累加,也就是中序遍历的反向。
利用双指针法,保存上一个结点的值,在这里可以用指针,也可以用int 值,因为只需要保存值。
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
TreeNode* pre = NULL;
void traversal(TreeNode* node) {
if (node == NULL) return;
traversal(node->right);
if (pre != NULL) node->val += pre->val;
pre = node;
traversal(node->left);
}
};