目录
一、235. 二叉搜索树的最近公共祖先
题目链接:力扣
文章讲解:代码随想录
视频讲解: 二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先
题目:
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
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);
else if (root->val < p->val && root->val < q->val)
return lowestCommonAncestor(root->right, p, q);
else
return root;
}
};
//迭代法
/*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;
}
};*/
时间复杂度: O(n) 空间复杂度: O(1)
⏲:3:01
总结:自底向上用后序遍历(同高度)。对比二叉树的最近祖先,二叉搜索树的特性可以帮助我们快速判断,祖先所在分支亦或确定是否为祖先。
二、701. 二叉搜索树中的插入操作
题目链接:力扣
文章讲解:代码随想录
视频讲解:原来这么简单? | LeetCode:701.二叉搜索树中的插入操作
题目:给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。 注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
//最简洁版
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* node, int val) {
if(node == nullptr) return new TreeNode(val);
if(node->val > val) node->left = insertIntoBST(node->left, val);
else node->right = insertIntoBST(node->right, val);
return node;
}
};*/
/*class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(!root) return new TreeNode(val);
if (root->val > val) {
if(!root->left){
TreeNode* node = new TreeNode(val);
root->left = node;
}
else insertIntoBST(root->left, val);
}
if (root->val < val) {
if(!root->right){
TreeNode* node = new TreeNode(val);
root->right = node;
}
else insertIntoBST(root->right, val);
}
return root;
}
};*/
时间复杂度: O(n) 空间复杂度: O(1)
⏲:4:21
总结:技巧:利用递归函数的返回值来完成父子节点的赋值,可以直接使用目标结点进行操作,从而避免需要通过父节点来进行操作。
三、450. 删除二叉搜索树中的节点
题目链接:力扣
文章讲解:代码随想录
视频讲解:调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点
题目:给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。 一般来说,删除节点可分为两个步骤: 首先找到需要删除的节点; 如果找到了,删除它。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(!root) return NULL;
if(root->val > key) root->left = deleteNode(root->left, key);
else if(root->val < key) root->right = deleteNode(root->right, key);
else{
if(!root->left) return root->right;
if(!root->right) return root->left;
TreeNode* new_root = root->left;
while(new_root->right) new_root = new_root->right;
new_root->right = root->right;
root = root->left;
}
return root;
}
};
用交换值的操作来删除目标节点:
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if (!root) return root;
if (root->val == key) {
if (!root->right) // 删除目标
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;
}
};
时间复杂度: O(n) 空间复杂度: O(n)
⏲:7:10
总结:方法一(最上面所用):通过将右子树拼在左子树最右侧,此方法操作简便,但是会让树变得畸形(层数大大增加)。
方法二:(交换这个)将左子树最右侧结点与目标结点进行交换,来代替。此方法让整体树形和之前保持较大程度一致。