LeetCode--单链表--114.二叉树展开为链表

给你二叉树的根结点 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

解法一:暴力遍历

遍历二叉树每个节点,把节点值存入list,再依次构建树。

class Solution {
    public void flatten(TreeNode root) {
        if (root==null){
            return;
        }
        List<TreeNode> order=new ArrayList<>();
        dfs(order,root);
        for (int i = 0; i < order.size()-1; i++) {
            order.get(i).right=order.get(i+1);
            order.get(i).left=null;
        }
    }

    private void dfs(List<TreeNode> order, TreeNode root) {
        if (root==null){
            return;
        }
        order.add(root);
        dfs(order,root.left);
        dfs(order,root.right);
    }
}

解法二:

  1. 将左子树插入到右子树的地方
  2. 将原来的右子树接到左子树的最右边节点
  3. 考虑新的右子树的根节点,一直重复上边的过程,直到新的右子树为 null
public void flatten(TreeNode root) {
    while (root != null) { 
        //左子树为 null,直接考虑下一个节点
        if (root.left == null) {
            root = root.right;
        } else {
            // 找左子树最右边的节点
            TreeNode pre = root.left;
            while (pre.right != null) {
                pre = pre.right;
            } 
            //将原来的右子树接到左子树的最右边节点
            pre.right = root.right;
            // 将左子树插入到右子树的地方
            root.right = root.left;
            root.left = null;
            // 考虑下一个节点
            root = root.right;
        }
    }
}

可能有人问,这里root = root.right是不是把root指向的内存空间改变了,讨论区有一位大佬解释了,

调用函数时,是在虚拟机栈的flatten方法创建的栈帧中的局部变量表里面,复制一个在main方法的栈帧的局部变量表中的指向头结点的head引用,移动的一直都是flatten方法的头结点,main方法里指向头结点一直都没移动,还是指向头结点,相当于调用flatten方法就复制了一个引用也指向树的头结点,一直操作的是这个复制的,方法结束就销毁,原来在main方法里的还是没动。

通俗点来说在flatten方法中使用的root只是main中的root的引用,相当于两个指针,都指向同一个二叉树。

另外这题还有很多种解法,递归啥的,后序遍历啥的,本人脑子太小,搞不懂,有兴趣的可以关注题解:
https://leetcode.cn/problems/flatten-binary-tree-to-linked-list/solution/

你可能感兴趣的:(Leetcode题解,链表,leetcode,算法)