LeetCode刷题笔记【17】:二叉树专题-9(修剪二叉搜索树、将有序数组转换为二叉搜索树、把二叉搜索树转换为累加树)

前置知识

参考前文

参考文章:
LeetCode刷题笔记【9】:二叉树专题-1(分别用递归遍历、迭代遍历、标记遍历实现前、中、后序遍历)
LeetCode刷题笔记【10】:二叉树专题-2(二叉树的层序遍历、翻转二叉树、对称二叉树)
LeetCode刷题笔记【10.5】:二叉树专题-2.5(二叉树的层序遍历 - 10道题)
LeetCode刷题笔记【11】:二叉树专题-3(二叉树的最大深度、二叉树的最小深度、完全二叉树的节点个数)
LeetCode刷题笔记【12】:二叉树专题-4(平衡二叉树、二叉树的所有路径、左叶子之和)
LeetCode刷题笔记【13】:二叉树专题-5(找树左下角的值 、路径总和、从前序与中序遍历序列构造二叉树、从中序与后序遍历序列构造二叉树)
LeetCode刷题笔记【14】:二叉树专题-6(最大二叉树 、合并二叉树 、二叉搜索树中的搜索 、验证二叉搜索树)4
LeetCode刷题笔记【15】:二叉树专题-7( 二叉搜索树的最小绝对差、二叉搜索树中的众数、二叉树的最近公共祖先)
LeetCode刷题笔记【16】:二叉树专题-8(二叉搜索树的最近公共祖先、二叉搜索树中的插入操作、删除二叉搜索树中的节点)

669. 修剪二叉搜索树

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/trim-a-binary-search-tree/

挨个处理节点, 将问题转化为"删除非法节点"

思路: 遍历二叉树, 在过程中进行删除操作
关于遍历: 在过程中使用递归, 具体使用方法是让root->left = funx(root->left) & root->right = funx(root->right)
关于删除:
① 如果root->leftroot->right都为nullptr, 直接delete root, return nullptr
② 如果左右子树其中一个为nullptr, 一个不是, 则delete root, 返回非nullptr的那个
③ 如果左右子树都非nullptr, 则将root->left拼贴到root->right的最深最左节点下的左节点

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        cout << "!!!" << endl;
        if(!root){
            cout << "本节点为空" << endl;
            return nullptr;
        }
        cout << root->val << endl;
        if(root->val<low || root->val>high){
            cout << "要删" << endl;
            if(root->left==nullptr && root->right==nullptr){
                cout << "左右都为空" << endl;
                // delete root;
                return nullptr;
            }else if(root->left==nullptr && root->right!=nullptr){
                cout << "左空右不空" << endl;
                TreeNode* tmp = root->right;
                // delete root;
                return trimBST(tmp, low, high);
            }else if(root->left!=nullptr && root->right==nullptr){
                cout << "右空左不空" << endl;
                TreeNode* tmp = root->left;
                // delete root;
                return trimBST(tmp, low, high);
            }else{
                cout << "左右都不空" << endl;
                TreeNode* cur = root->right;
                while(cur->left != nullptr){
                    cur = cur->left;
                }
                cur->left = root->left;
                TreeNode* tmp = root->right;
                // delete root;
                return trimBST(tmp, low, high);
            }
        }
        cout << root->val << endl;
        cout << "不删" << endl;
        root->left = trimBST(root->left, low, high);
        root->right = trimBST(root->right, low, high);
        cout << root->val << " final check" << endl;
        return root;
    }
};

参考这一期笔记中的最后一题, 方法思路是一样的.

LeetCode刷题笔记【16】:二叉树专题-8(二叉搜索树的最近公共祖先、二叉搜索树中的插入操作、删除二叉搜索树中的节点)

这里特别说一下, LeetCode的线上编译器其实有一定问题, 比如上面代码中的delete用法是对的, 并不会造成野指针和悬挂指针之类的问题, 但是LeetCode就是会报错, 但是本地编译器却不会.

原因可能是LeetCode可能将我要删除的节点指到什么乱七八糟的地方去了.

利用二叉搜索树性质, 直接大量剪枝

刚才的方法也是可以的, 但是它并没有完全利用到二叉搜索树的性质和特点
但其实如果cur->val<low, 那么curNode以及其left, 都需要被删掉, 所以只要返回funx(cur->right)即可
同理, if(cur->val>high), return funx(cur->left)

// class Solution {
// public:
//     TreeNode* trimBST(TreeNode* root, int low, int high) {
//         if(!root){
//             return nullptr;
//         }
//         if(root->val<low){
//             return trimBST(root->right, low, high);
//         }else if(root->val>high){
//             return trimBST(root->left, low, high);
//         }
//         root->left = trimBST(root->left, low, high);
//         root->right = trimBST(root->right, low, high);
//         return root;
//     }
// };

108.将有序数组转换为二叉搜索树

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/description/

解题思路

思路: 用限位指针leftright, 每次选取下标为(left+right)/2的数, 建立node
node->left = funx(left, position-1), node->right = funx(position+1, right)
left>right的时候return

代码

class Solution {
public:
    TreeNode* build(vector<int>& nums, int left, int right){
        if(left>right)
            return nullptr;
        int position = (left+right)/2;
        TreeNode* node = new TreeNode(nums[position]);
        node->left = build(nums, left, position-1);
        node->right = build(nums, position+1, right);
        return node;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return build(nums, 0, nums.size()-1);
    }
};

538.把二叉搜索树转换为累加树

题目描述

在这里插入图片描述
在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/convert-bst-to-greater-tree/description/

解题思路

我们知道: 二叉搜索树如果进行中序遍历, 就可以得到递增序列;
那么同理, 如果进行反中序遍历, 就可以得到递减序列;

这样一来, 在过程中用一个sum记录之前遍历过的节点的val;
然后每遍历一个节点, 将这个节点的val加入sum, 并将此节点的val设为加后的sum.

代码

class Solution {
private:
    int sum=0;
public:
    TreeNode* convertBST(TreeNode* root) {
        if(root!=nullptr){
            convertBST(root->right);
            sum += root->val;
            root->val = sum;
            convertBST(root->left);
        }
        return root;
    }
};

总结

首先是血泪教训: 很多时候LeetCode的报错并不是我们写的有问题, 就是他自己(的编译器)有问题.
(摸到自己编译环境的上限并琢磨明白或许是水平提高的特点呢(小小骄傲一下))

其次是今天第三题这种, 利用二叉搜索树中序遍历结果递增, 并且用pre和cur抽取其中的前后关系, 的操作, 还是不够熟练.

530. 二叉搜索树的最小绝对差
501. 二叉搜索树中的众数
之后可以多刷刷这几题

本文参考:
修剪二叉搜索树
将有序数组转换为二叉搜索树
把二叉搜索树转换为累加树

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值