LeetCode 114.二叉树展开为链表

129 阅读2分钟

「这是我参与2022首次更文挑战的第35天,活动详情查看:2022首次更文挑战」。

题目:给定二叉树的根节点root,要求将此二叉树展开为一个链表,链表要求如下:

  1. 二叉树展开后的链表结构应该同样使用原始TreeNode数据结构,并且其左指针指向空,右指针指向链表的下一个节点。
  2. 二叉树展开后的链表应该和二叉树的先序遍历保持相同顺序。

解题思路

本题要求最终的链表顺序和二叉树的先序遍历保持相同,那么可以将二叉树先得到先序遍历的结果,之后修改结果集合中的每个节点的指针指向即可,获得先序遍历的方式有递归法和非递归法,递归法较为简单,可得如下代码:

	public void flatten(TreeNode root) {
		if(root==null) return;
        ArrayList<TreeNode> temp = new ArrayList<>();
        preOrder(root, temp);
        for(int i=1;i<temp.size();i++){
            TreeNode pre = temp.get(i-1), curr=temp.get(i);
            pre.left = null;
            pre.right=curr;
        }
    }

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

上述代码时间复杂度和空间复杂度都为O(n)O(n)。非递归法和之前先序遍历一样,都需要使用栈数据结构,此处使用的是Java中的 双端队列ArrayDeque 作为栈,可得如下代码:

public void flatten(TreeNode root) {
        if(root==null) return;
        TreeNode cur = root;
        ArrayDeque<TreeNode> deque = new ArrayDeque<>();
        ArrayList<TreeNode> list = new ArrayList<>();
        deque.push(cur);
        while (!deque.isEmpty()){
            cur = deque.pop();
            list.add(cur);
            if(cur.right!=null){
                deque.push(cur.right);
            }
            if(cur.left!=null){
                deque.push(cur.left);
            }
        }
        for(int i=1;i<list.size();i++){
            TreeNode pre = list.get(i-1), curr=list.get(i);
            pre.left = null;
            pre.right=curr;
        }
    }

上述代码中最后一个for循环中的i值为0时,就代表的是root节点,因此最终结果属于原地修改。但代码的时间复杂度和空间复杂度仍为O(N)O(N)。而题中要求使用O(1)O(1)空间复杂度来展开,如何解决呢?参考评论区一位大佬的题解,虽然我写不出来~ 代码如下:

TreeNode last = null;
public void flatten(TreeNode root) {
    if(root==null) return;
    flatten(root.right);
    flatten(root.left);
    root.right=last;
    root.left=null;
    last=root;
}

代码相对于官方题解容易理解的多,最终耗时为0ms,空间复杂度为O(1)O(1)