判断 BST 的非法
最容易想到的就是套用咱们的先序遍历框架
boolean isValidBST(TreeNode root){if(root==null){return true;}
if(root.left!=null&&root.val<=root.left.val){return false;}
if(root.right!=null&&root.val>=root.right.val){return false;}
return isValidBST(root.left)&&isValidBST(root.right);
}
减少参数列表, 在参数中携带额定信息, 通过辅助函数将下层节点的束缚传递下来
boolean isValidBST(TreeNode root,TreeNode min,TreeNode max){if(root==null){return true;}
boolean isValidBST(TreeNode root,TreeNode min,TreeNdoe max){
//base case
if(root==null){return true;}
// 若 root.val 不合乎 max 和 min 的限度, 阐明不是非法 BST
if(min!=null&&root.val<=min.val) return false;
if(max!=null&&root.val>=max.val)return false;
// 限定左子树的最大值是 root.val,右子树的最小值是 root.val
return isValidBST(root.left,min,root)&&isValidBST(root.right,root,max);
}
在 BST 中搜寻一个数
这个比较简单,间接放框架代码
void BST(TreeNode root,int target){if(root.val==target){// 找到指标, 做点什么}
if(root.val<target){BST(root.right,target);
}
if(root.val>target){BST(root.left,target);
}
}
在 BST 中插入一个数
一旦波及[改], 函数就要返回 TreeNode 类型, 并且对递归调用的返回值进行接管
TreeNode insertIntoBST(TreeNode root,int val){
// 找到空地位插入新节点
if(root==null){return new TreeNode(val);
}
//if(root.val==val)
//BST 中个别不会插入已存在的元素
if(root.val<val){root.right=insertIntoBST(root.right,val);
}
if(root.val>val){root.left=insertIntoBST(root.left,val);
}
return root;
}
在 BST 中删除一个数(重点)
TreeNode deleteNode(TreeNdde root,int key){if(root.val==key){// 找到啦,进行删除}else if(root.val>key){
// 去左子树找
root.left=deleteNode(root.left,key);
}else if(root.val<key){
// 去右子树找
root.right=deleNode(root.right,key);
}
return root;
}
思考删除节点时咱们须要干什么?
状况 1:A 恰好是末端节点, 两个节点都为空, 那么它能够当场逝世了
if(root.left==null&&root.right==null){return null;}
状况 2:A 只有一个非空子节点, 那么它要让这个孩子接替本人的地位
if(root.left==null) return root.right;
if(root.right==null) return root.left;
状况 3:A 有两个子节点,为了不毁坏 BST 的性质,A 必须找到左子树中最大的那个节点,或者右子树中最小的那个节点来接替本人。
if(root.left!=null&&root.right!=null){
// 找到右子树的最小节点
TreeNode minNode=getMin(root.right);
// 把 root 改成 minNode
root.val=minNode.val;
// 删除 minNode
root.right=deleteNode(root.rigth,minNode.val);
}
框架代码
TreeNode deleteNode(TreeNode root,int key){if(root==null){return null;}
if(root==key){
// 这两个 if 把状况1和2都正确地解决了
if(root.left==null) return right;
if(root.right==null) return left;
// 解决状况 3
TreeNode minNode=getMin(root.right,minNode.val);
root.val=minNdode.val;
root.right=deleteNode(root.right,minNode.val);
}else if(root.val>key){root.let=deleteNode(root.left,key);
}else if(root.val<key){root.right=deleteNode(root.right,key);
}
return root;
}
TreeNdoe getMin(TreeNode node){
//BST 最右边的就是最小的
while(node.left!=null){node=node.left;}
}
最初总结
1. 如果以后节点会对上面的子节点有整体影响,能够通过辅助函数增长参数列表
2.BST 框架代码
void BST(TreeNode root, int target) {if (root.val == target)
// 找到指标,做点什么
if (root.val < target)
BST(root.right, target);
if (root.val > target)
BST(root.left, target);
}