宁波市内做公司网站的公司,开发网站监控工具,专业网站设计 网络服务,在线crm视频在线crm235 二叉搜索树的最近公共祖先
如果利用普通二叉树的方法#xff0c;就是利用后序遍历回溯从低向上搜索#xff0c;遇到左子树有p#xff0c;右子树有q#xff0c;那么当前结点就是最近公共祖先。本题是二叉搜索树#xff0c;所以说是有序的#xff0c;一定能够简化上面…235 二叉搜索树的最近公共祖先
如果利用普通二叉树的方法就是利用后序遍历回溯从低向上搜索遇到左子树有p右子树有q那么当前结点就是最近公共祖先。本题是二叉搜索树所以说是有序的一定能够简化上面的方法。如果中间节点是p和q的公共祖先那么他一定是在p和q区间的即中节点 p 中节点 q 或者 中节点 q 中节点 p。所以在每次遍历时都加上这个判断条件会比较好。递归代码如下
class Solution {
private:TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q) {if (cur NULL) return cur;// 中if (cur-val p-val cur-val q-val) { // 左TreeNode* left traversal(cur-left, p, q);if (left ! NULL) {return left;}}if (cur-val p-val cur-val q-val) { // 右TreeNode* right traversal(cur-right, p, q);if (right ! NULL) {return right;}}return cur;}
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return traversal(root, p, q);}
}; 当然本题代码还可以精简
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;}
}; 701 二叉搜索树的插入操作
进行二叉搜索树的插入操作并不需要调整二叉树的结构因为特殊性每次插入的结点都能插入到叶子上面所以递归的方法就比较简单了
class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {if (root NULL) {TreeNode* node new TreeNode(val);return node;}if (root-val val) root-left insertIntoBST(root-left, val);if (root-val val) root-right insertIntoBST(root-right, val);return root;}
}; 本题也可以利用迭代法
class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {//如果为空节点此时直接进行插入说明是一颗空树if (root NULL) {TreeNode* node new TreeNode(val);return node;}TreeNode* cur root; //记录当前的结点TreeNode* parent root; // 这个很重要需要记录上一个节点否则无法赋值新节点while (cur ! NULL) {parent cur; //上一个结点接连等于当前结点之后当前结点变动if (cur-val val) cur cur-left;else cur cur-right;}//此时遍历到空节点了也就是要插入val的位置TreeNode* node new TreeNode(val);if (val parent-val) parent-left node;// 此时是用parent节点的进行赋值else parent-right node;return root;}
}; 450 删除二叉搜索树中的结点
注意此时有些情况就需要改变二叉树的结构了因为删除的并不一定是叶子节点。
class Solution {
public:TreeNode* deleteNode(TreeNode* root, int key) {if(root nullptr) return root; //如果是空节点直接返回说明没有找到要删除的节点if(root-val key){//要删除的节点为叶子结点if(root-leftnullptrroot-rightnullptr){delete root;return nullptr;}//要删除的节点左空右不空if(root-leftnullptrroot-right!nullptr){TreeNode* node root-right;delete root;return node;}//要删除的结点左不空右空if(root-left!nullptrroot-rightnullptr){TreeNode* node root-left;delete root;return node;}//要删除的节点左右都不空让右面的结点顶替他当然左面的也可以这里只写一种if(root-left!nullptrroot-right!nullptr){TreeNode* cur root-right;while(cur-left) cur cur-left;cur-leftroot-left;TreeNode* tmp root;root root-right;delete tmp;return root;}}if(root-val key) root-left deleteNode(root-left, key);if(root-val key) root-right deleteNode(root-right, key);return root;}
}; 这里我在介绍一种通用的删除普通二叉树的删除方式没有使用搜索树的特性遍历整棵树用交换值的操作来删除目标节点。
代码中目标节点要删除的节点被操作了两次
第一次是和目标节点的右子树最左面节点交换。第二次直接被NULL覆盖了。 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;}
}; 迭代法
class Solution {
private:// 将目标节点删除节点的左子树放到 目标节点的右子树的最左面节点的左孩子位置上// 并返回目标节点右孩子为新的根节点// 是动画里模拟的过程TreeNode* deleteOneNode(TreeNode* target) {if (target nullptr) return target;if (target-right nullptr) return target-left;TreeNode* cur target-right;while (cur-left) {cur cur-left;}cur-left target-left;return target-right;}
public:TreeNode* deleteNode(TreeNode* root, int key) {if (root nullptr) return root;TreeNode* cur root;TreeNode* pre nullptr; // 记录cur的父节点用来删除curwhile (cur) {if (cur-val key) break;pre cur;if (cur-val key) cur cur-left;else cur cur-right;}if (pre nullptr) { // 如果搜索树只有头结点return deleteOneNode(cur);}// pre 要知道是删左孩子还是右孩子if (pre-left pre-left-val key) {pre-left deleteOneNode(cur);}if (pre-right pre-right-val key) {pre-right deleteOneNode(cur);}return root;}
};