赞
踩
相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性。
题目链接/文章讲解:代码随想录
这道题明晃晃就要是要利用二叉搜索树的节点大小的特点,如果当前节点的值比这两个的都要大,那就往左边找(单独左子树递归即可),如果当前的值比这两个的值都要小那就往右边找(单独右子树递归即可),如果恰好处于中间的一个值,那就证明当前节点就是最近公共祖先,然后返回给上个节点的递归即可(这么找上个节点必然是这个节点的父母节点,所以必然比这两个数都大或小),再直接返回找到的结果即可——
- TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
- // if(root==NULL||root==p||root==q) return root;
- if(root->val<min(p->val,q->val)){
- return lowestCommonAncestor(root->right,p,q);
- }
- if(root->val>max(p->val,q->val)){
- return lowestCommonAncestor(root->left,p,q);
- }
- return root;
- }
其实,一旦遇到二叉搜索树,迭代法就会很简单,因为二叉搜索树的题它一般都是要利用它的节点大小特点,所以搜索的路径一般都是固定的。这题的思路和递归的一样——
- TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
- while(root){
- if(root->val>max(p->val,q->val)) root=root->left;
- else if(root->val<min(p->val,q->val)) root=root->right;
- else return root;
- }
- return NULL;
- }
本题比想象中的简单,大家可以先自己想一想应该怎么做,然后看视频讲解,就发现 本题为什么比较简单了。
题目链接/文章讲解:代码随想录
这道题首先说可以不调整节点,就说明可以将所有加入的节点都放在叶子节点处,不调整整棵树,这样就会简单很多。
使用递归的方法,首先要明确递归何时结束,也就是当当前节点为空的时候,就意味着要返回你的新节点了(已经到达了当前树的叶子节点),如果当前不为空,就要判断当前节点的值大于还是小于加入的值,然后直接将递归调用的返回节点作为当前节点的左子树或右子树,然后最后返回整棵树,作为上一层的左子树或右子树——
- TreeNode* insertIntoBST(TreeNode* root, int val) {
- if(root==NULL) return new TreeNode(val);
- if(root->val>val) root->left=insertIntoBST(root->left,val);
- if(root->val<val) root->right=insertIntoBST(root->right,val);
- return root;
- }
迭代法是很简单的,就是找到合适的叶子节点处,然后给这个叶子节点加一个子节点即可——
- TreeNode* insertIntoBST(TreeNode* root, int val) {
- if(root==NULL) return new TreeNode(val);
- TreeNode* cur=root;
- TreeNode* pre=NULL;
- while(cur){
- pre=cur;
- if(cur->val>val) cur=cur->left;
- else cur=cur->right;
- }
- cur=new TreeNode(val);
- if(pre->val>val) pre->left=cur;
- else pre->right=cur;
- return root;
- }
相对于 插入操作,本题就有难度了,涉及到改树的结构
题目链接/文章讲解:代码随想录
这道题其实主要是要搞懂怎么删除节点,要删除的节点分成三种情况:
- TreeNode* aided(TreeNode* node){
- if(node->left==NULL&&node->right==NULL) {
- delete(node);
- return NULL;
- }
- TreeNode* tmp=node;
- if(node->left&&node->right==NULL){
- tmp=tmp->left;
- delete(node);
- return tmp;
- }
- if(node->right&&node->left==NULL){
- tmp=tmp->right;
- delete(node);
- return tmp;
- }
- tmp=tmp->right;
- while(tmp->left){
- tmp=tmp->left;
- }
- tmp->left=node->left;
- tmp=node->right;
- delete(node);
- return tmp;
- }
- TreeNode* deleteNode(TreeNode* root, int key) {
- if(!root) return NULL;
- if(root->val==key){
- return aided(root);
- }else if(root->val>key) root->left=deleteNode(root->left,key);
- else root->right=deleteNode(root->right,key);
- return root;
- }

文章还给出了删除普通二叉树的方法,就是当要删除的节点本身没有右孩子的时候,直接返回左孩子,如果有右孩子,那就将右孩子的最左边的孩子的值和当前节点的值交换一下,一直交换到目标节点的右孩子为空为止,这样再直接返回目标节点的左孩子。这样做本质上是没有对要删除的节点进行彻底的空间释放——
- 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的父节点,用来删除cur
- while (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;
- }
- };

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。