[刷题记录Day22]Leetcode二叉树
No.1
题目
二叉搜索树的最近公共祖先
思路
- 递归法
- BST特性如何利用?在BST中,公共祖先一定在p、q数值范围的中间
- 利用BST特性定向搜索
- 注意递归遍历一条边和遍历整棵树的写法不同
递归分析
- 返回值:节点,参数:当前节点,p,q
- 终止逻辑:发现当前节点为空,则直接返回当前节点;
- 为什么不用判断p和q与root值的情况?因为不需要遍历到p和q实际的值,通过范围的剪枝就可以找到p、q的方向
- 单层递归分析:p、q都大于当前节点,则向右子树搜索;p、q都小于当前节点,则向左子树搜索;当前节点在p、q中间,则直接返回当前节点;
代码
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null)
return root;
if (root.val > p.val && root.val > q.val) {
TreeNode leftTree = lowestCommonAncestor(root.left, p, q);
// 有结果直接返回,即这条边遍历结束,无需继续搜索
if (leftTree != null)
return leftTree; // return 终止当前递归函数
}
if (root.val < p.val && root.val < q.val) {
TreeNode rightTree = lowestCommonAncestor(root.right, p, q);
if (rightTree != null)
return rightTree;
}
// 为什么排除上门2种情况后的root一定是最近公共祖先?很重要
// 只剩下root val在p和q之间的情况
return root;
}
No.2
题目
二叉搜索树中的插入操作
思路
- BST,沿着一条路径递归
递归分析
- 返回值:节点,记录插入位置,参数:当前节点,和待插入的值
- 终止逻辑:终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回
- 单层递归逻辑:待插入值比当前值小,left指向递归返回;待插入值比当前值大,right指向递归返回;
代码
有返回值,用下一层递归返回值赋值给本层
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) {
return new TreeNode(val);
}
if (root.val < val)
root.right = insertIntoBST(root.right, val);
if (root.val > val)
root.left = insertIntoBST(root.left, val);
return root;
}
无返回值
private TreeNode pre = null;
private void insertHelper(TreeNode node, int val) {
if (node == null) {
TreeNode temp = new TreeNode(val);
if (pre.val < temp.val)
pre.right = temp;
if (pre.val > temp.val)
pre.left = temp;
return;
}
if (node.val < val) {
pre = node;
insertHelper(node.right, val);
}
if (node.val > val) {
pre = node;
insertHelper(node.left, val);
}
}
public TreeNode insertIntoBST(TreeNode root, int val) {
// 提前滤除直接给空树的情况
if (root == null)
return new TreeNode(val);
// 至少1个节点,递归开始后,pre一定不为null
insertHelper(root, val);
return root;
}
No.3
题目
删除二叉搜索树中的节点
思路
- 递归
递归分析
- 返回值:删除节点后的子树根,参数:节点,要删除的值
- 终止条件:遇到空节点,说明没找到要删除的节点
- 单层递归过程:五种情况
- 第一种情况:没找到删除的节点,遍历到空节点直接返回了
- 找到删除的节点,第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
- 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
- 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
- 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
代码