代码随想录算法【Day20】
Day20
二叉搜索树
235. 二叉搜索树的最近公共祖先
理解只要当前节点的值在p和q节点的值的中间,那这个值就是最近的公共祖先,绝对不是次近的,这个题就好做了。
递归法
二叉搜索树本身是有序的,所以不涉及到前中后序的遍历
class Solution { private: TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q){ //先判断当前节点为空的情况 if(cur == NULL) return NULL; //当前节点的值大于p和q节点的值,则遍历当前节点的左子树 if(cur->val > p->val && cur->val > q->val){ TreeNode* left = traversal(cur->left, p, q); return left; } 当前节点的值小于p和q节点的值,则遍历当前节点的右子树 if(cur->val < p->val && cur->val < q->val){ TreeNode* right = traversal(cur->right, p, q); return right; } return cur; } public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { return traversal(root, p, q); } };
迭代法
使用while循环进行迭代
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
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; } };
递归法2
迭代法
450.删除二叉搜索树中的节点
难点在于删除之后,要怎样去调整树的结构
添加节点的情况,不用去改二叉搜索树的结构,一定找到一个合适的叶子结点的位置
删除节点的情况,要分五种情况去分析:
①没找到要删的节点
②删除的节点,其左为空,右为空,即叶子结点
③删除的结点,其左不空,右为空,直接让父节点指向其子节点
④删除的结点,其左为空,右不空,直接让父节点指向其子节点
⑤删除的结点,其左不空,右不空,假如我们删除节点7,如下:
我们固定我们的删除方法,即让右孩子当新的父节点,并让左孩子连接到右孩子最左侧节点上
class Solution { public: TreeNode* deleteNode(TreeNode* root, int key) { // 代码整体是一个递归的结构 // ①没找到要删的节点 if(root == nullptr) return root; if(root -> val == key){ // ②删除的节点,其左为空,右为空,即叶子结点 if(root -> left == nullptr && root -> right == nullptr){ delete root; return nullptr; } // ③删除的结点,其左不空,右为空,直接让父节点指向其子节点 else if(root -> right == nullptr){ TreeNode *retNode = root -> left; delete root; return retNode; } // ④删除的结点,其左为空,右不空,直接让父节点指向其子节点 else if(root -> left == nullptr){ TreeNode *retNode = root -> right; delete root; return retNode; } // ⑤删除的结点,其左不空,右不空 else{ // 先找到右孩子最左侧的节点 TreeNode *cur = root -> right; while(cur -> left != nullptr) cur = cur -> left; cur -> left = root -> 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; } };
代码虽然很多,只要慢慢分析是不难的,不能有畏难情绪。