235. 二叉搜索树的最近公共祖先
- 对于二叉搜索树的最近公共祖先来说,可以从上到下去遍历,只要遇到的结点在[p, q]区间中,即可说明该结点就是q 和 p 的公共祖先。
- 此时可能会疑惑,找到的公共祖先一定是最近的吗,答案是的。 因为一旦找到了公共祖先,那么(假设 p 的值比 q 的值小 )p 一定在公共结点的左子树里,q 一定在公共结点的右子树里。如果继续往左 或者 往右遍历,你不是错过了p 就是错过了 q。
- 递归和迭代都可以,因为二叉搜索树是有序的,不需要整个遍历。
递归法
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) || (root->val >= q->val && root->val <= p->val)) return root;
if (root->val < p->val && root->val < q->val) {
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if (right != NULL) return right;
}
if (root->val > p->val && root->val > q->val) {
TreeNode* left = lowestCommonAncestor(root->left, p, q);
if (left != NULL) return left;
}
return NULL;
}
};
迭代法
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
while (root != NULL) {
if (root->val < p->val && root->val < q->val) {
root = root->left;
continue;
}
if (root->val > p->val && root->val > q->val) {
root = root->right;
continue;
}
return root;
}
return NULL;
}
};
701.二叉搜索树中的插入操作
对于二叉搜索树来说,要插入一个与树中结点都不相同的结点,在叶子结点都可以找到它的位置
如果找到对应的叶子结点,插入时 是需要父节点的。所以可以通过递归函数返回值进行回溯, 来接住
不然就需要再定义一个结点
递归函数带返回值
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (root == NULL) {
TreeNode* node = new TreeNode(val);
return node;
}
if (val < root->val) {
root->left = insertIntoBST(root->left, val);
}
if (val > root->val) {
root->right = insertIntoBST(root->right, val);
}
return root;
}
};
递归函数不带返回值
class Solution {
public:
TreeNode* parent;
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (root == NULL) {
root = new TreeNode(val);
}
//parent = new TreeNode(0);
traversal(root, val);
return root;
}
void traversal(TreeNode* root, int val) {
if (root == NULL) {
TreeNode* node = new TreeNode(val);
if (val > parent->val) parent->right = node;
else parent->left = node;
return;
}
parent = root;
if (val > root->val) {
traversal(root->right, val);
}
if (val < root->val) {
traversal(root->left, val);
}
return;
}
};
450.删除二叉搜索树中的节点
对于该题,需要考虑的情况比较多,分为5种
(1)二叉搜索树中没有要删除的结点
(2)要删除的结点位叶子结点,左右孩子均为空
(3)要删除的结点左孩子为空,右孩子不为空
(4)要删除的结点右孩子为空,左孩子不为空
(5)要删除的结点左右孩子均不为空
最后一种情况是最复杂的,可以采取以下两种方式进行求解:将左子树接到右子树最左边的结点的左边;或者 将右子树街道左子树最右边的结点的右边,这样就转化为 3、4 两种情况。
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if (root == NULL) return NULL;
if (root->val == key) {
if (root->left == NULL && root->right == NULL) {
delete root;
return NULL;
} else if (root->left != NULL && root->right == NULL) {
auto cur = root->left;
delete root;
return cur;
} else if (root->left == NULL && root->right != NULL) {
auto cur = root->right;
delete root;
return cur;
} else {
TreeNode* node = root->right;
while(node->left != NULL) {
node = node->left;
}
node->left = root->left;
auto cur = root->right;
delete root;
return cur;
}
}
if (key > root->val) {
root->right = deleteNode(root->right, key);
}
if (key < root->val) {
root->left = deleteNode(root->left, key);
}
return root;
}
};