235. 二叉搜索树的最近公共祖先
解题思路:
利用二叉搜索树特性,最近公共祖先数值大小一定位于p和q的数值之间,(或者就是p或q本身)。
因此遍历节点时:
若p和q数值都大于当前节点,则该节点数值过小,向右遍历。
若p和q数值都小于当前节点,则该节点数值过大,向左遍历。
以上情况都不符合,包含两种情况:
①当前遍历的节点数值位于p和q数值之间,则该节点为最近公共祖先,返回该节点。
②当前遍历节点数值大于/小于 p和q之间的一个节点,则该节点就是p/q之中的另一节点。该节点为最近公共祖先,返回该节点。
递归法:
直接向左右子树递归遍历即可,不需要遍历中间节点。
当遍历到空节点时,说明不存在最近公共祖先,返回null即可。
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null){return null;}
if(root.val>p.val && root.val>q.val){TreeNode left=lowestCommonAncestor(root.left,p,q); return left;}
else if(root.val<p.val && root.val<q.val){TreeNode right=lowestCommonAncestor(root.right,p,q); return right;}
return root;
}
迭代法:
当遍历节点不为空时,一直想左右子树遍历直到为空/找到停止。
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root!=null){
if(root.val > p.val && root.val > q.val){
root=root.left;
}
else if(root.val < p.val && root.val < q.val){
root=root.right;
}else{
return root;
}
}
return root;
}
701.二叉搜索树中的插入操作
递归解题思路:
利用搜索二叉树特性,当val小于当前节点数值时,则val位于该节点的左侧。反之在右侧。因此自顶向上遍历可以一直递归遍历,一定可以将val插入在当前树的叶子结点中。
当遍历到空节点时,则代表此处为即将要插入的叶子结点。创建一个新节点存放val,并返回该节点作为其上一个节点的子树即可。然后将结果一直向上返回直至根节点。
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root==null){
TreeNode node=new TreeNode(val);
return node;
}
if(root.val>val){
root.left=insertIntoBST(root.left,val);
}
if(root.val<val){
root.right=insertIntoBST(root.right,val);
}
return root;
}
450.删除二叉搜索树中的节点
这道题挺难的哈哈哈,勉强看懂。
解题思路:
首先,本题有五种情况:
①没找到被删除节点(后面四种都是找到的情况)
②被删除节点左右子树都为空,直接返回null
③当左子树为空,返回右子树
④当右子树为空,返回左子树
⑤最复杂的情况:被删除节点的左右子树都不为空。
此时根据搜索二叉树的特性,当节点被删除后,其左子树可以连接在其右子树的最左侧叶子结点上。反之亦然。
递归解法:
当前遍历节点数值大时,删除的节点一定在当前节点左侧,因此要修改root.left的值。返回删除好的子树作为当前节点的左子树。反之亦然。最后将结果层层递归返回到根节点上。成为一个新的二叉搜索树。
public TreeNode deleteNode(TreeNode root, int key) {
//第一种情况:没找到,返回null
if(root==null){return root;}
//当前遍历节点数值大时,删除的节点一定在当前节点左侧,因此要修改root.left的值。返回删除好的子树作为当前节点的左子树
if(root.val>key){root.left=deleteNode(root.left,key);}
//反之亦然
if(root.val<key){root.right=deleteNode(root.right,key);}
else if(root.val==key){
//第二、三种情况:当左子树为空,返回右子树(当右子树也为空时同样返回右子树——null)
if(root.left==null){
return root.right;
//第四种情况:右子树为空,返回左子树
}else if(root.right==null){
return root.left;
}else{
//第五种情况,左右都不为空 —— 将被删除节点的左子树作为右子树的最左侧叶子
//令cur指向被删除右子树的最左侧叶子结点
TreeNode cur=root.right;
while(cur.left!=null){
cur=cur.left;
}
//将被删除节点的左子树连接在cur的左子树上
cur.left=root.left;
//返回root的右子树,作为root父节点的新右子树。
root=root.right;
return root;
}
}
return root;
}