二叉树展开为链表

87 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

一、题目

leetcode 二叉树展开为链表

给你二叉树的根结点 root ,请你将它展开为一个单链表:

展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。 展开后的单链表应该与二叉树 先序遍历 顺序相同。  

示例 1:*

输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [0]
输出:[0]

提示:

树中结点数在范围 [0, 2000] 内
-100 <= Node.val <= 100

二、题解

需要将二叉树转为一个二叉树形态的单链表,并且前序遍历的结果都要相同。

方法一 首先前序遍历的访问顺序先是根节点,然后是左节点,最后是右节点。既然都要求前序遍历的结果得一致,那么我们就可以用前序遍历来构造。可以先使用前序遍历获取原二叉树的所有节点,然后得到的是一个前序遍历顺序的节点集合,然后我们在顺序遍历这个节点集合来构造单链表树,左节点都默认为空,然后右节点就是当前遍历的节点。

方法二 如果对于根节点为1,左节点为2,右节点为3的一个二叉树,如果要变为单链表,那么首先需要将左节点移到根节点的右节点上,然后再吧原本的右节点移到现在的右节点的右节点上,这样可以应用到每个子树上。所以整体看起来就是先将左子树如果左子树不为空的话,然后再把右子树也变为一个连表,最后把右子树的链表移到左子树的链表的右节点上。

三、代码

方法一 Java代码

class Solution {
    List<TreeNode> treeList = new ArrayList<TreeNode>();
    public void flatten(TreeNode root) {
        getTreeList(root);
        int size = treeList.size();
        for (int i = 1; i < size; i++) {
            TreeNode node = treeList.get(i - 1);
            node.left = null;
            node.right = treeList.get(i);
        }
    }

    public void getTreeList(TreeNode tree) {
        if (tree == null) {
            return;
        }
        treeList.add(tree);
        getTreeList(tree.left);
        getTreeList(tree.right);
    }
}

时间复杂度:O(n),需要一次前序遍历二叉树获取节点集合,一次遍历节点集合构造单链表。

空间复杂度:O(n),需要节点集合存储前序遍历的结果已经递归栈空间。


方法二 Java代码

class Solution {
    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        }
        flatten(root.left);
        flatten(root.right);
        TreeNode temp = root.right;
        root.right = root.left;
        root.left = null;
        while (root.right != null) {
            root = root.right;
        }
        root.right = temp;
    }
}

时间复杂度:O(n),需要遍历节点已经递归栈空间。

空间复杂度:O(1),只需常数的空间。