三种解法

二叉搜索树与双向链表

http://www.nowcoder.com/questionTerminal/947f6eb80d944a84850b0538bf0ec3a5

方法1

首先最容易想到的,是用一个数组来存储中序遍历的节点,然后再从头到尾,建立节点前后的连接关系。代码如下:

import java.util.ArrayList;
public class Solution {
    public TreeNode Convert(TreeNode pRootOfTree) {
        if (pRootOfTree==null)
            return null;
       ArrayList<TreeNode> list=new ArrayList<>();
       Convert(list,pRootOfTree);
       return Convert(list);
    }

    public void Convert(ArrayList<TreeNode>list,TreeNode root){
        if (root!=null){
            Convert(list,root.left);
            list.add(root);
            Convert(list,root.right);
        }
    }

    public TreeNode Convert(ArrayList<TreeNode> list){
        TreeNode head=list.get(0);
        TreeNode cur=head;
        for (int i=1;i<list.size();++i){
            TreeNode node=list.get(i);
            node.left=cur;
            cur.right=node;
            cur=node;
        }
        return head;
    }
}

方法2

接着想怎么优化。我们知道二叉排序树中序遍历的结果是排好序的,然后再想到线索化二叉树的过程,很容易联想到用线索化二叉树的方法去做,用一个全局变量去保存前一个节点,然后再去创建节点之间的关系(这里区别与线索化二叉树的是,线索化二叉树创建节点之间的关系是在节点的左右孩子为空的时候采取创建,这样二叉树还是二叉树。但是这里就不是,只要pre不空,就创建关系,创建后就是链表了,二叉树被破坏了)。这里推荐一下我自己写的有关二叉树的博客:https://blog.csdn.net/qq_31709249/article/details/103092783,这里面有详细讨论二叉树的各种问题。除了讨论二叉树,还讨论了常见的各种数据结构,此外自己学习过程中包括的笔记,包括计算机网络计算机操作系统Java虚拟机,都非常认真的整理了,并且还在不断补充更新中,有需要的小伙伴可以看看,希望大家都可以拿到自己心仪的offer呀!

那参考线索化二叉树的创建过程,我们的代码应该是这样子的:

public class Solution {
    TreeNode pre=null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if (pRootOfTree==null)
            return null;
        Convert(pRootOfTree.left);
        if (pre!= null){
            pRootOfTree.left=pre;
            pre.right=pRootOfTree;
        }
        pre=pRootOfTree;
        Convert(pRootOfTree.right);
        return pre;
    }
}

这里我们发现返回的双向链表是降序排列的,那我们有两种解决方法,第一种是再遍历一遍得到的结果,将节点的最后一个结果返回。第二种是设置一个变量来记录,我 这里采用第二种方法:

public class Solution {
    TreeNode pre=null;
    TreeNode root=null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if (pRootOfTree==null)
            return null;
        Convert(pRootOfTree.left);
        if (root==null){
            root=pRootOfTree;
        }
        if (pre!= null){
            pRootOfTree.left=pre;
            pre.right=pRootOfTree;
        }
        pre=pRootOfTree;
        Convert(pRootOfTree.right);
        return root;
    }
}

方法3

再想,我们受到惯性思维的约束,每次都是想着中序遍历先遍历左子树,再遍历根节点,再遍历右子树。那既然第二种方法得到的二叉树是降序的,那我先遍历右子树,再遍历根节点,再遍历左子树不就可以了么,所以有了 第三种解法,代码和第二种大致一样:

public class Solution {
    TreeNode pre=null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if (pRootOfTree==null)
            return null;
        Convert(pRootOfTree.right);
        if (pre!= null){
            pRootOfTree.right=pre;
            pre.left=pRootOfTree;
        }
        pre=pRootOfTree;
        Convert(pRootOfTree.left);
        return pre;
    }
}

三种方法自己提交时的运行时间;
方法1:21ms
方法2:18ms
方法3:15ms

全部评论
要求不能创建任何新的结点 要求不能创建任何新的结点 要求不能创建任何新的结点
2 回复 分享
发布于 2020-08-18 05:05
在测试用例中,系统是认为pre是正序的表头,即先从左往右看看对不对,到表尾之后再从右往左看对不对。 在正常的中序遍历完成时,pre是最右边/最大值的结点;也就是正序的表尾; 而系统又把pre当作正序表头,这样得到的双向链表pre先从左往右走,只有自己;再从右往左走,符合。 所以我们要么 按中序的反序 右-左-根;要么得到pre之后,再找到正序的表头;
1 回复 分享
发布于 2020-08-15 14:18
方法3完美,2和3的本质是用pre来保存每个节点在中序里的前一个节点的引用,然后用pre.left = root; root.right = pre来建立双向连接,然后再用pre = root来更新pre,2是从左到右进行遍历,3是从右到左进行遍历,3结束的时候pre刚好指向最左边的节点
1 回复 分享
发布于 2020-07-31 13:01
请问下各位大哥,方法2.1为什么不行呢? 楼主说的“这里我们发现返回的双向链表是降序排列的”是什么意思呢?
1 回复 分享
发布于 2020-05-17 19:52
优雅简洁❤
点赞 回复 分享
发布于 2022-08-18 16:47 重庆
请问方法1的空间复杂度是O(1)吗?
点赞 回复 分享
发布于 2021-10-17 09:45
妙极啦
点赞 回复 分享
发布于 2021-08-12 22:14
方法3为什么不能返回值pRootOfNode
点赞 回复 分享
发布于 2021-06-06 17:58
线索二叉树
点赞 回复 分享
发布于 2021-04-24 16:52
大佬太强了
点赞 回复 分享
发布于 2021-04-13 23:51
三个函数取了一模一样的名字,看得我直犯迷糊
点赞 回复 分享
发布于 2020-08-13 10:11
方法二的TreeNode pre=null;会不会不满足“不能创建新的结点”这个要求?
点赞 回复 分享
发布于 2020-07-09 11:47
写的好啊
点赞 回复 分享
发布于 2020-07-06 17:21
妙哉
点赞 回复 分享
发布于 2020-06-25 22:36
方法1最后为什么不是返回cur 而是head啊
点赞 回复 分享
发布于 2020-04-11 10:37
太强了
点赞 回复 分享
发布于 2020-04-07 00:12
对于方法2可以详细解释下吗,我是真的看不懂
点赞 回复 分享
发布于 2020-04-01 20:42
太好了
点赞 回复 分享
发布于 2020-03-28 10:17

相关推荐

评论
155
26
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务