最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 恢复二叉搜索树多种解法

    正文概述 掘金(Stoney_S)   2021-03-21   465

    1  题目介绍

    1.1  题目介绍

    给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
    **进阶:**使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?

    实例一

    恢复二叉搜索树多种解法

    输入:root = [1,3,null,null,2]
    输出:[3,1,null,null,2]
    解释:3 不能是 1 左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
    

    题目来源:leetcode-cn.com/problems/re…

    1.2  题目分析

    在分析之前,先介绍一个概念:前驱节点,二叉搜索树的前驱节点指中序遍历的前一个节点;

    二叉搜索树中序遍历的结果是一个递增的数组;正常的二叉搜索树中序遍历结果如下图

    恢复二叉搜索树多种解法

    交换中序遍历前驱节点中序遍历如下图所示

    恢复二叉搜索树多种解法

    交换其他节点中序遍历如下图所示

    恢复二叉搜索树多种解法

    以上分析得出以下结果

    • 第1个错误节点:第一个逆序对中的较大节点
    • 第2个错误节点:最后一个逆序对中的较小节点;
    • 交换两个错误节点的值即可恢复二叉搜索树;

    2  中序遍历寻找逆序对实现

    采用递归方法进行中序遍历寻找逆序对;

    var recoverTree = function(root) {
        let pre = null;
        let first = null;
        let second = null;
        findWrongNodes(root);
        // 交换两个错误节点值
        let tmp = first.val;
        first.val =  second.val;
        second.val = tmp;
    
        function findWrongNodes(root) {
            // 中序遍历寻找逆序对
            if(root == null) return;
            findWrongNodes(root.left);
            find(root);
            findWrongNodes(root.right);
        }
    
        function find(node) {
            // 出现了逆序对
            if(pre !== null && pre.val > node.val) {
                // 第二个错误的节点,最后一个逆序对中较小的那个节点
                second = node;
                // 第一个错误节点,第一个逆序对中较大的那个节点
                if(first != null) return;
                first = pre;
            }
            pre = node;
        }
    };
    

    时间复杂度:O(n);
    空间复杂度:O(n);

    3  Morris遍历寻找逆序对实现

    使用Morris方法遍历二叉树,可以实现时间复杂度O(n),空间复杂度O(1);

    3.1  Morris遍历介绍

            Morris遍历是一种常数空间的遍历方法,其本质是线索二叉树(Threaded Binary Tree);Morris遍历是利用树的叶子节点左右孩子为空(存在大量空闲指针),实现缩减空间开销;Morris中序遍历是指在遍历过程中,通过利用叶子节点空的right指针,指向中序遍历的后继节点,从而避免了对栈的依赖;实现空间复杂的降为O(1); 下面介绍二叉搜索树中序遍历的Morris遍历;

    3.2  分析

    恢复二叉搜索树多种解法

    执行步骤

    假设遍历到当前节点是N

    1. 如果N.left != null,找到N的前驱节点P;
      a,如果P.right == null; P.right = N, N = N.left; 回到步骤1
      b,如果P.right == N; P.right = null, 此时N为中序遍历的节点,N = N.right, 回到步骤1;
    2. 如果N.left == null;即找到中序遍历的节点,N = N.right,回到步骤1
    3. 重复步骤1,2直到N == null;

    3.3  代码实现

    var recoverTree = function(root) {
        let pre = null;
        let first = null;
        let second = null;
        
        while(root != null) {
            if(root.left != null) {
                let pred = root.left;
                while(pred.right !== null && pred.right != root) {
                    pred = pred.right;
                }
                if(pred.right == null) {
                    pred.right = root;
                    root = root.left;
                } else {
                    find(root);
                    pred.right = null;
                    root = root.right;
                }
            } else {
                find(root);
                root = root.right;
            }
        }
    
        let tmp = first.val;
        first.val =  second.val;
        second.val = tmp;
    
        function find(node) {
            // 出现了逆序对
            if(pre !== null && pre.val > node.val) {
                // 第二个错误的节点,最后一个逆序对中较小的那个节点
                second = node;
                // 第一个错误节点,第一个逆序对中较大的那个节点
                if(first != null) return;
                first = pre;
            }
            pre = node;
        }
    };
    

    时间复杂度:O(n);
    空间复杂度:O(1);


    起源地下载网 » 恢复二叉搜索树多种解法

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元