235. 二叉搜索树的最近公共祖先
1. LeetCode链接
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
2. 题目描述
3. 解法
利用二叉搜索树的特性进行公共节点的判断:
1. 此节点为公共节点:p、q恰好在此节点的左右棵子树上。即,root的val在p、q的val所构成的闭区间内。
2. 如果p、q的val恰好都大于root的val,则只需要考虑root->right
3. 如果p、q都小于root,则只考虑root->left
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 >= p->val && root->val <= q->val) return root;else if (p->val > root->val && q->val > root->val) return lowestCommonAncestor(root->right, p, q);else return lowestCommonAncestor(root->left, p, q);}
};
更精简一点
class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if (p->val > root->val && q->val > root->val) return lowestCommonAncestor(root->right, p, q);else if (p->val < root->val && q->val < root->val) return lowestCommonAncestor(root->left, p, q);else return root;}
};
迭代法
class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {queue<TreeNode*> qu;qu.push(root);TreeNode* cur;while (!qu.empty()) {cur = qu.front();qu.pop();if (q->val < cur->val && p->val < cur->val) qu.push(cur->left);else if (q->val > cur->val && p->val > cur->val) qu.push(cur->right);else break;}return cur;}
};
更加精简的:
class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {while(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;} else return root;}return NULL;}
};
701. 二叉搜索树中的插入操作
1. LeetCode链接
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
2. 题目描述
3. 解法
先在二叉搜索树中查询val,直到找到NULL,然后将val插入该NULL。
迭代:
class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {TreeNode* a = new TreeNode(val);if (root == NULL) return a;TreeNode* cur = root;while (cur) {if (cur->val > val && cur->left != NULL) cur = cur->left;else if (cur->val > val && cur->left == NULL) {cur->left = a;break;}else if (cur->val < val && cur->right != NULL) cur = cur->right;else {cur->right = a;break;}}return root;}
};
递归。相当于将在遍历至NULL的路上,重新连接原本的树,直到遇到NULL,然后把NULL换成val。
1. 参数和返回值。参数:当前节点和val。返回值:当前节点。
2. 终止条件。遇到NULL且将NULL替换为val。
3. 比较root和val确定从左子树走还是右子树走,root->left = root->left / root->right = root->right;
class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {if (root == NULL) {TreeNode* n = new TreeNode(val);return n;}if (root->val > val) root->left = insertIntoBST(root->left, val);if (root->val < val) root->right = insertIntoBST(root->right, val);return root;}
};
450. 删除二叉搜索树中的节点
1. LeetCode链接
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
2. 题目描述
3. 解法
删除节点后,需要考虑是让左子树上位还是右子树上位。这道题的话,无所谓,暂且让左子树上位吧。这个时候问题来了,右子树该如何安排?
其实这道题目可以看成左子树上位后,将右子树插入左子树,因为两边都是二叉搜索树,且左子树必小于右子树,所以只要简单插入即可。
class Solution {
public:TreeNode* insertNode(TreeNode* root, TreeNode* key) {if (root == NULL) return key;if (key == NULL) return root;if (key->val > root->val) root->right = insertNode(root->right, key);if (key->val < root->val) root->left = insertNode(root->left, key);return root;}TreeNode* deleteNode(TreeNode* root, int key) {if (root == NULL) return NULL;if (root->val == key) {TreeNode* left = root->left;TreeNode* right = root->right;delete root;return insertNode(left, right);}if (key > root->val) root->right = deleteNode(root->right, key);if (key < root->val) root->left = deleteNode(root->left, key);return root;}
};
细想的话,其实如果将左子树上位,右子树一定被插在左子树中的最右节点的右节点上;如果让右子树上位,左子树一定被插在最左节点的左节点上。
class Solution {
public:TreeNode* deleteNode(TreeNode* root, int key) {if (root == NULL) return NULL;if (root->val == key) {TreeNode* left = root->left;TreeNode* right = root->right;delete root;if (left == NULL) return right;if (right == NULL) return left;TreeNode* cur = left;while (left != NULL && left->right != NULL) left = left->right;left->right = right;return cur;}if (key > root->val) root->right = deleteNode(root->right, key);if (key < root->val) root->left = deleteNode(root->left, key);return root;}
};
更巧妙的是,删除当前节点后,最合适的候选节点是左子树最右节点或者右子树最左节点。可以通过交换val值,将root换到底部,然后再遇到root后直接删除。
class Solution {
public:TreeNode* deleteNode(TreeNode* root, int key) {if (root == nullptr) return root;if (root->val == key) {if (root->right == nullptr) { // 这里第二次操作目标值:最终删除的作用return root->left;}TreeNode *cur = root->right;while (cur->left) {cur = cur->left;}swap(root->val, cur->val); // 这里第一次操作目标值:交换目标值其右子树最左面节点。}root->left = deleteNode(root->left, key);root->right = deleteNode(root->right, key);return root;}
};