代码随想录算法训练营第二十二天| 235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点
235. 二叉搜索树的最近公共祖先
问题简述:找出二叉搜索树的最近公共祖先。
思考:想了一会感觉是这么做的,结果也没啥问题。
算法思路:先序遍历,返回最早出现的在两个结点数值之间的结点。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return null;
//先序遍历
if (root.val >= Math.min(p.val, q.val) && root.val <= Math.max(p.val, q.val)){
//最先找到在q、p之间的结点为公共祖先
return root;
}
//返回左右子树找到的不为空的那个结点
return (lowestCommonAncestor(root.left, p, q) != null) ? lowestCommonAncestor(root.left, p, q): lowestCommonAncestor(root.right, p, q);
}
}
701.二叉搜索树中的插入操作
问题简述:在二叉搜索树中插入新结点。
思考:插入比删除简单太多,而且这道题不需要递归。
算法思路:依次从跟结点开始,比较结点值与key的大小,同时每次记录当前节点的父结点,当当前节点为空时,在记录的父结点下添加节点。
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
//用于遍历结点
TreeNode p = root;
//用于记录p的父结点
TreeNode lastnode = null;
//如果当前结点为空,返回新建立的结点
if (root == null) return new TreeNode(val);
while (p != null){
//保留p的父结点
lastnode = p;
//比较val与当前结点大小
if (val > p.val){
p = p.right;
}else if (val < p.val) {
p = p.left;
}
}
//定义新结点
TreeNode t = new TreeNode(val);
//新结点插入lastnode的左或右
if (lastnode.val > val){
lastnode.left = t;
}else {
lastnode.right = t;
}
return root;
}
}
450.删除二叉搜索树中的节点
问题简述:删除二叉搜索树中的节点,保证删除后仍为二叉搜索树。
思考:感觉是非常有难度的一道题,开始自己试着写了一堆,还是有错误。看了视频感觉还是挺难,主要是想不到递归可以直接返回结点,一直在想着需要找到父结点的事情。
算法思路:递归先序遍历节点,如果当前节点为空,则返回null;其次判断当前节点是否与目标值相等,如果不相等则递归遍历左右子树,并将当前节点连接删除结点后的左右子树;如果相等则进行删除并且有以下几种情况:
- 删除结点为叶子结点:直接返回null,递归过程中父节点会直接连接null。
- 删除结点只有一个孩子:则直接返回那个孩子,递归过程中父节点会直接连接那个孩子。
- 删除结点有两个孩子:将左孩子接到右孩子上,接法是放到右孩子的最左孩子的左孩子上,再返回这个当前节点的右孩子。(将右孩子接到左孩子同理)
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
//如果为空返回null
if (root == null) return null;
if (root.val == key){
//为叶子结点,则直接返回null
if (root.left == null && root.right == null){
return null;
}
//如果只有一个孩子
if (root.left == null && root.right != null) return root.right;
if (root.right == null && root.left != null) return root.left;
//如果有两个孩子
TreeNode p = root.left;
while (p.right != null){
p = p.right;
}
p.right = root.right;
return root.left;
}
//最关键的一步,因为我们每次将root左右指向删除后的子树,所以上面可以直接返回结点
if (key > root.val) root.right = deleteNode(root.right, key);
if (key < root.val) root.left = deleteNode(root.left, key);
return root;
}
}
感想
想吃烧烤