235. 二叉搜索树的最近公共祖先
普通二叉树的最近公共祖先方法通用,但是涉及到二叉排序树的特性,就需要记得遍历得到的最近的一个值在p q值之间的结点,这个就是目标的公共祖先结点。这题算是写的比较透的了,用了三种方法。
class Solution {
public:TreeNode* traversal(TreeNode* root, TreeNode* p, TreeNode* q){// 1、以下是普通搜索树的方法// if (root == nullptr || root == p || root == q) return root;// TreeNode* left = traversal(root->left, p, q);// TreeNode* right = traversal(root->right, p, q);// if (left && right) return root;// else if (!left && right) return right;// else if (left && !right) return left;// else return nullptr;// 2、以下是用了二叉搜索树特性的方法if (root == nullptr) return root;// 并不是每次都遍历左右,而是视情况而定if (root->val > p->val && root->val > q->val){// 当前值大于两个目标值,则向左遍历TreeNode* left = traversal(root->left, p ,q);// 相当于把找到的值一直传上去if (left != nullptr){return left;}}if (root->val < p->val && root->val < q->val){// 当前值小于两个目标值,则向右遍历TreeNode* right = traversal(root->right, p ,q);if (right != nullptr){return right;}}// 两种情况都不符合,不递归了,直接返回当前节点,这个是最先找到的祖先节点return root;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {// return traversal(root, p, q);// 3、迭代写法TreeNode* cur = root;while (cur != nullptr){if (cur->val > p->val && cur->val > q->val){cur = cur->left;}else if (cur->val < p->val && cur->val < q->val){cur = cur->right;}else{return cur;}}return nullptr;}
};
701. 二叉搜索树中的插入操作
考研的时候我记得好像就背过如何建一棵排序二叉树,当时就觉得好简单,现在看也简单的,但是不容易写出来。递归写法最重要的就是利用回溯的特点,用上一层的结点接住下一层的返回值,二分查找得到的空节点就可以返回一个新建的结点。迭代写法需要用一个父节点记录找到的插入位置的父节点,从而用父节点接着新建结点。
class Solution {
public:TreeNode* traversal(TreeNode* root, int val){// 按照二叉搜索树的特性遍历二叉树,如果遇到空节点就是要插入的结点,返回新建的节点if (root == nullptr){TreeNode* node = new TreeNode(val);return node;}// 用root的孩子接住返回的结点if (root->val > val) root->left = traversal(root->left, val);if (root->val < val) root->right = traversal(root->right, val);return root;}TreeNode* insertIntoBST(TreeNode* root, int val) {// 1、迭代法// if (root == nullptr){// TreeNode* node = new TreeNode(val);// return node;// }// null不是特定节点,因此不可记录位置,需要用一个父节点记录要插入位置的前一个节点// TreeNode* pre = root;// TreeNode* cur = root;// while (cur != nullptr){// pre = cur;// if (val > cur->val){// cur = cur->right;// }// else if (val < cur->val){// cur = cur->left;// }// }// TreeNode* node = new TreeNode(val);// if (val < pre->val){// pre->left = node;// }// else if (val > pre->val){// pre->right = node;// }// return root;//return traversal(root, val);}
};
450. 删除二叉搜索树中的节点
这题更是重量级,如果没写过真的很难写出来。包括现在我也云里雾里的,感觉可以算是hard题了。因为删除需要考虑的状况有点多,所以情况也复杂一些。当然我觉得用迭代会更简单点,但是现在不想深究它了。二刷再来掌握。
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->left == nullptr){auto retNode = root->right;delete root;return retNode;}else if (root->right == nullptr){auto retNode = root->left;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;}
};