LeetCode——二叉树篇(八)

刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com

目录

236. 二叉树的最近公共祖先 

235. 二叉搜索树的最近公共祖

         迭代

递归

701. 二叉搜索树中的插入操作

450. 删除二叉搜索树中的节点

236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 *(思路:对于一个结点,只要其左子树出现p或q,或右子树出现p或q,那么该节点就是节点p和q的最近公共                    
    祖先;
 *如果递归遍历遇到q,就将q返回,遇到p就将p返回,那么如果左右子树的返回值都不为空,说明此时的中节 
    点,一定是q和p的最近祖先。
 *
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //递归结束条件
		if(root==p||root==q||root==null){
			return root;
		}

		//左
		TreeNode left=lowestCommonAncestor(root.left,p,q);
		//右
		TreeNode right=lowestCommonAncestor(root.right,p,q);

		//中
		if(left!=null&&right!=null){
			return  root;  //最近公共祖先
		}else if(left==null&&right!=null){
			return right;   // 若找到一个节点  继续向上返回直到根节点
		} else if (left != null && right == null) {
			return left;   // 若找到一个节点  继续向上返回直到根节点
		}else {
			return null;   //没找到结点
		}
    }
}

235. 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

 迭代

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
			//迭代
        while (root!=null){
			if(root.val>=p.val&&root.val<=q.val||root.val<=p.val&&root.val>=q.val||root==null){
				return root;
			}
			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;
			}
		}
		return root;
    }
}

递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    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=lowestCommonAncestor1(root.left,p,q);
			if(left!=null){
				return left;
			}
		}
		if(root.val<p.val&&root.val<q.val){
			TreeNode right=lowestCommonAncestor1(root.right,p,q);
			if(right!=null){
				return right;
			}
		}
		return root;
    }
}

701. 二叉搜索树中的插入操作

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 * (思路:其实可以不考虑题目中提示所说的改变树的结构的插入方式。
 * 只要按照二叉搜索树的规则去遍历,遇到空节点就插入节点就可以了。
 */
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        //递归终止条件,当遍历到空节点时,就是要插入节点的时候,返回要插入的节点
		if(root==null){
			TreeNode node=new TreeNode(val);
			return node;
		}
		if(root.val<val){
			root.right=insertIntoBST(root.right,val);
		}
		if(root.val>val){
			root.left=insertIntoBST(root.left,val);
		}
		return  root;
    }
}

450. 删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 * (思路:删除二叉树中节点可以分为以下几种情况:
 * 		1.未找到要删除的节点
 * 		2.找到要删除的节点:
 * 			2.1	删除节点为叶子结点---直接删除
 * 			2.2 删除节点不是叶子结点,但其左孩子为空,右孩子不为空---直接让其父节点指向该节点的右孩子
 * 			2.3	删除节点不是叶子结点,但其右孩子为空,左孩子不为空---直接让其父节点指向该节点的左孩子
 * 			2.4 删除节点不是叶子结点,且左右孩子均不为空:
 * 				右孩子继位,将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上

 */
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        //递归终止条件:遇到空直接返回(没找到要删除的节点
		if(root==null){
			return null;
		}
		//找到要删除的节点:返回删除后的根节点
		if(root.val==key){
			//1.删除节点为叶子结点
			if(root.left==null&&root.right==null){
				return null;
			} else if (root.left!=null&&root.right==null) { //2.删除节点左孩子不为空
				return root.left;
			} else if (root.right != null&&root.left==null) { //3.删除节点右孩子不为空
				return root.right;
			}else{  //4.删除节点左右孩子均不为空
				TreeNode node=root.right;
				while(node.left!=null){
					node=node.left;    //找到右子树的最左边的节点
				}
				node.left=root.left;   //把要删除的节点(root)左子树放在cur的左孩子的位置
				return root.right;
			}
		}
	if(root.val>key){
			root.left=deleteNode(root.left, key);
		}
		if(root.val<key){
			root.right=deleteNode(root.right,key);
		}
		return root;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值