代码随想录 669.修剪二叉搜索树

思路:在修剪二叉搜索树的时候,同样可能会改变树的根节点,因此和450.删除二叉搜索树中的节点一样,需要把删除掉的节点的孩子节点赋值给其父亲节点,如下图所示。
(1)目的:修剪该二叉搜索树使所有的节点的值在[1,3]中,涉及到了节点的重新赋值。

(2)删除节点0后无需重构二叉树,只需将节点0的右孩子节点2直接赋给节点3的左孩子就可以了(实现了把节点0从二叉树中移除)。

方法一:深度优先搜索递归。
递归三部曲:
1.确定递归函数的参数和返回值:
(1)参数:根节点root,最小边界low和最大边界high。
(2)返回值:因为是遍历整棵树做修改,因此不用返回值也可以完成修剪(从二叉树中移除节点)的操作,但是有返回值更方便,可以通过递归函数的返回值来移除节点。
TreeNode trimBST(TreeNode root, int low, int high)2.确定终止条件:修剪的操作并不是在终止条件上进行的,所以遇到空节点返回就可以了。
if (root == null) {return null;}3.确定单层递归的逻辑:
(1)如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头节点。
(2)如果root(当前节点)的元素大于high的数值,那么应该递归左子树,并返回左子树符合条件的头节点。
(3)接下来将下一层处理完左子树的结果赋值给root.left,处理完右子树的结果赋值给root.right,最后返回root节点。
if (root.val < low) {//寻找符合区间[low,high]的节点TreeNode right = trimBST(root.right, low, high);return right;}if (root.val > high) {//寻找符合区间[low,high]的节点TreeNode left = trimBST(root.left, low, high);return left;}// root在[low,high]范围内//root.left接住符合条件的左孩子root.left = trimBST(root.left, low, high);//root.right接住符合条件的右孩子root.right = trimBST(root.right, low, high);return root;
还原二叉树被移除的过程:上述代码在针对下图中二叉树的情况:

如下代码相当于把节点0的右孩子(节点2)返回给上一层。
if (root.val < low) {//寻找符合区间[low,high]的节点TreeNode right = trimBST(root.right, low, high);return right;}然后如下代码相当于用节点3的左孩子,把下一层返回的节点0的右孩子(节点2)接住。
//root.left接住符合条件的左孩子root.left = trimBST(root.left, low, high);此时节点3的左孩子就变成了节点2,将节点0从二叉树中移除了。
附代码:
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;}
}方法二:迭代法,因为二叉搜索树的有序性,不需要栈模拟递归。
在剪枝的时候,可以分为3步:
1.将root移动至[L,R]范围内,注意是左闭右闭区间。
2.剪枝左子树。
3.剪枝右子树。
附代码:
class Solution {public TreeNode trimBST(TreeNode root, int low, int high) {if(root == null){return root;}while(root != null && (root.val < low || root.val > high)){if(root.val < low){root = root.right;}else{root = root.left;}}TreeNode cur = root;while(cur != null){while(cur.left != null && cur.left.val < low){cur.left = cur.left.right;}cur = cur.left;}cur = root;while(cur != null){while(cur.right != null && cur.right.val > high){cur.right = cur.right.left;}cur = cur.right;}return root;}
}