669. 修剪二叉搜索树
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。
所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
示例 1:
输入:root = [1,0,2], low = 1, high = 2
输出:[1,null,2]
示例 2:
输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3
输出:[3,2,null,1]
思考
其实大致思路是和删除二叉树节点相同的。唯一不同的是,这里需要在次从被删除后顶替的节点开始,因为你不知道该节点是不是满足条件,如果不满足即可删除该节点。
- 删除二叉搜索树中的节点
删除二叉树可以参考上一篇文章:删除二叉搜索树的节点
我们删除一个节点,首先考虑特殊情况
- 该树为空,直接返回null
- 该节点为树的根节点,并且没有左右子树,返回null
前序遍历函数
- 处理
- 遍历左子树
- 遍历右子树
定义前序遍历递归,其参数
- pre代表访问该节点的父节点,初始化为null
- root代表正在访问的节点
- key
其递归需要返回值 ,因为会出现两种情况
- 如果删除的节点不是根节点,preOrder函数返回null,deleteNode返回root
- 如果删除的节点是根节点,preOrder函数返回新的根tempRoot,deleteNode返回tempRoot
前序遍历函数处理过程:
- 如果该节点的值等于key,说明需要删除此节点
此图代表right和left都非空时
-
root代表需要删除的节点
-
left代表root的左孩子(可能为null)
-
right代表root的右孩子(可能为null)
-
pre代表root的父节点,但是我们不知道root是pre的左孩子还是右孩子
- 但是由于该树是搜索二叉树,所以我们可以根据pre.val和root.val来判断
-
我们只需把b(可能为null)移动到c(可能为null)的左子树即可
注意:还有left和right可能为空的情况,这里不在画图赘述,大致相同。
public static TreeNode trimBST(TreeNode root, int low, int high) {
if(root==null) return null;
if(root.val<low||root.val>high){
if(root.left==null&&root.right==null)
return null;
}
TreeNode[] treeRoot=new TreeNode[1];
preOrder(treeRoot,null,root,low,high);
return treeRoot[0];
}
private static void preOrder(TreeNode[] treeRoot,TreeNode pre, TreeNode root, int low, int high) {
TreeNode temproot = null;
int k = 0;
if(root.val<low||root.val>high){
k = 1;
TreeNode left=root.left;
TreeNode right=root.right;
if(right==null&&left!=null){
temproot = left;
}else if(right!=null){
if(left==null){
temproot=right;
}else{
TreeNode righttemp = right;
while (righttemp.left!=null){
righttemp = righttemp.left;
}
righttemp.left=left.right;
left.right=right;
temproot =left;
}
}
// pre 为空
if(pre==null){
treeRoot[0] = temproot;
}
if(pre!=null){
if(pre.val>root.val){
pre.left= temproot;
}
if(pre.val<root.val){
pre.right=temproot;
}
}
}
if(k==1&&temproot!=null)//修改了root节
preOrder(treeRoot,pre, temproot, low, high);
else {
if(k==0&&root.left!=null)
preOrder(treeRoot,root, root.left, low, high);
if(k==0&&root.right!=null)
preOrder(treeRoot,root, root.right, low, high);
}
}