中等
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
while (root != NULL) {
if (root->val > val) root = root->left;
else if (root->val < val) root = root->right;
else return root;
}
return NULL;
}
};
// 迭代法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while (true) {
if (root.val > p.val && root.val > q.val) { // 当root在两节点右边时
root = root.left;
} else if (root.val < p.val && root.val < q.val) { // 当root在两节点左边时
root = root.right;
} else { // root.val 处于 p.val 和 root.val 之间
return root;
}
}
}
}
// 递归法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q); // 当root在两节点右边时
if (root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);// 当root在两节点左边时
return root; // root.val 处于 p.val 和 root.val 之间
}
}
中等
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果
假设在上图插入一个1.5,那么肯定选5这个节点的左边,注意,此时,就不用再管会不会大过5的右子树了,因为5的右子树肯定比5大,你都比5小了,就不用跟别人比了。然后和3比,发现没3大,此时往左走,那么3的右子树就不用想着可能比1.5小了。走到1,再往右走到2,此时左边界是1,右边界是2,就这样确定下来了。所以,为什么往下这样插入可以满足二叉搜索树?因为每经过一个节点都确定了一个边界。
// 迭代法
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
TreeNode node = new TreeNode(val); // 待插入节点
TreeNode cur = root;
TreeNode pre = root;
if (root == null) return node;
while (cur != null) {
pre = cur;
if (cur.val > val) {
cur = cur.left;
} else {
cur = cur.right;
}
}
if (pre.val > val) {
pre.left = node;
} else {
pre.right = node;
}
return root;
}
}
// 递归法,这个还是需要想一想的
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
if (val < root.val) {
root.left = insertIntoBST(root.left, val);
} else {
root.right = insertIntoBST(root.right, val);
}
return root;
}
}
中等
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return null;
if (root.val == key) {
// 如果找到的这个节点是叶子节点或者只有左或者右节点
if (root.left == null) return root.right;
if (root.right == null) return root.left;
// 如果找到的这个节点下面挂着俩节点,那就交换它和右子树最大节点(或左子树最小节点)的位置
TreeNode minNode = getMin(root.right);
//在最小节点本来的位置删除这个最小节点
root.right = deleteNode(root.right, minNode.val); // 这里是通过赋值的方式来删除的,,不是你传进去一个节点就能删了,所以别忘了root.right= ... 这里一定要把删除后的子树接住
// 用右子树最小的节点替换 root 节点
minNode.left = root.left;
minNode.right = root.right;
root = minNode;
} else if (root.val > key) {
root.left = deleteNode(root.left, key); // 这里老是忘记写 root.left =
} else if (root.val < key) {
root.right = deleteNode(root.right, key);
}
return root;
}
public TreeNode getMin(TreeNode node) {
while (node.left != null) { // 一直往左找就能找到最小的
node = node.left;
}
return node;
}
}
以下内容来自:https://labuladong.github.io/algo/
// labuladong代码
TreeNode deleteNode(TreeNode root, int key) {
if (root == null) return null;
if (root.val == key) {
// 这两个 if 把情况 1 和 2 都正确处理了
if (root.left == null) return root.right;
if (root.right == null) return root.left;
// 处理情况 3
// 获得右子树最小的节点
TreeNode minNode = getMin(root.right);
// 删除右子树最小的节点
root.right = deleteNode(root.right, minNode.val);
// 用右子树最小的节点替换 root 节点
minNode.left = root.left;
minNode.right = root.right;
root = minNode;
} else if (root.val > key) {
root.left = deleteNode(root.left, key);
} else if (root.val < key) {
root.right = deleteNode(root.right, key);
}
return root;
}
TreeNode getMin(TreeNode node) {
// BST 最左边的就是最小的
while (node.left != null) node = node.left;
return node;
}