LeetCode 235.二叉搜索树的最近公共祖先
题目链接:235.二叉搜索树的最近公共祖先
踩坑:root->val在p和q之间时不需要再向下递归了,此时root就是最近公共祖先。
思路:根据二叉搜索树的特性,可以在递归过程中选择递归方向(q和p均大于root,q和p均小于root,root在q和p之间)。需要注意的是,当root在q和p之间时,root就是当前最近公共祖先。因为再向下会错过q或p,向上root只能作为某棵树的子树。
代码:
/**
* 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) return NULL;
if(root->val == q->val || root->val == p->val) return root;
if(p->val > q->val) swap(p, q);
TreeNode* left = NULL;
TreeNode* right = NULL;
if(root->val < p->val)
{
right = lowestCommonAncestor(root->right, p, q);
}
else if(root->val < q->val && root->val > p->val)
{
return root;
}
else if(root->val > q->val)
{
left = lowestCommonAncestor(root->left, p, q);
}
if(left && right) return root;
if(left && !right) return left;
if(!left && right) return right;
return NULL;
}
};
LeetCode 701.二叉搜索树中的插入操作
题目连接:701.二叉搜索树中的插入操作
踩坑:想复杂了,一直在考虑从升序序列下手,还要改结构。
思路:核心是每一个插入的数都可以在叶子节点找到相应的位置。需要注意的是,对于递归函数的设计,如果明确其返回值是当前二叉树的根节点,就要按照这个思路来设计停止条件和单层逻辑,不能直接在停止条件处为叶子节点的孩子赋值。
代码:
/**
* 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* root, int val) {
if(!root)
{
TreeNode* t = new TreeNode(val);
return t;
}
if(val < root->val) root->left = insertIntoBST(root->left, val);
if(val > root->val) root->right =insertIntoBST(root->right, val);
return root;
}
};
LeetCode 450.删除二叉搜索树中的节点
题目链接:450.删除二叉搜索树中的节点
踩坑:不知道删除节点后该怎么修改二叉树的结构
思路:一共五种情况,1.找不到需要删除的节点,2.要删除的节点是叶子,3.要删除的节点只有左孩子,4.要删除的节点只有右孩子,5.要删除的节点左右孩子都有。明确了函数返回的是删除了目标节点的根节点之后,1情况即遍历到null所以返回null。2情况因为要删除叶子节点所以也返回null。3情况只需要返回左孩子即可。4情况只需要返回右孩子即可。5情况稍微复杂一些,可以选择返回左孩子或者右孩子,这里以返回右孩子为例,因为右孩子都是大于根节点的,当根节点被删除,左根节点是仅小于根节点的,所以需要挂在右子树中仅大于根节点的叶子的左孩子。而仅大于根节点的节点位于右子树的左下角。
代码:
/**
* 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 nullptr;
if(root->val == key)
{
if(!root->left && !root->right) return nullptr;
else if(!root->left && root->right) return root->right;
else if(root->left && !root->right) return root->left;
else
{
TreeNode* t = root->right;
while(t->left) t = t->left;
t->left = root->left;
return root->right;
}
}
if(key < root->val) root->left = deleteNode(root->left, key);
if(key > root->val) root->right = deleteNode(root->right, key);
return root;
}
};