zoukankan      html  css  js  c++  java
  • Medium | LeetCode 114. 二叉树展开为链表 | 先序遍历 | 递归 | 迭代

    114. 二叉树展开为链表

    给定一个二叉树,原地将它展开为一个单链表。

    例如,给定二叉树

        1
       / 
      2   5
     /    
    3   4   6
    

    将其展开为:

    1
     
      2
       
        3
         
          4
           
            5
             
              6
    

    方法一:递归先序遍历保存进List

    public void flatten(TreeNode root) {
        List<TreeNode> list = new ArrayList<TreeNode>();
        // 先使用递归先序遍历, 将其值保存进List
        preorderTraversal(root, list);
        // 然后遍历List, 将前一个节点和后一个节点串联起来
        int size = list.size();
        for (int i = 1; i < size; i++) {
            TreeNode prev = list.get(i - 1), curr = list.get(i);
            prev.left = null;
            prev.right = curr;
        }
    }
    
    public void preorderTraversal(TreeNode root, List<TreeNode> list) {
        if (root != null) {
            list.add(root);
            preorderTraversal(root.left, list);
            preorderTraversal(root.right, list);
        }
    }
    

    方法二:递归子树, 返回链表头结点和尾节点

    类似于 Medium | LeetCode 426 | 剑指 Offer 36. 二叉搜索树与双向链表 | 中序遍历(递归) 在递归的时候, 返回链表的头结点和尾节点。

    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        }
        preorderTraversal(root);
    }
    
    public TreeNode[] preorderTraversal(TreeNode root) {
        if (root == null) {
            return new TreeNode[2];
        }
        // 递归计算左右子树链表的头结点和尾节点
        TreeNode[] left = preorderTraversal(root.left);
        TreeNode[] right = preorderTraversal(root.right);
    
        root.left = null;
        if (left[0] != null) {
            // 如果左子树不为空, 则将其插在根节点和右子树链表中间
            root.right = left[0];
            left[1].right = right[0];
        } else {
            // 没有左子树, 则将右子树链表直接插在根节点后面
            root.right = right[0];
        }
    	// 根据左右子树的返回值情况设置当前树的链表的头结点和尾节点
        if (right[1] != null) {
            return new TreeNode[]{root, right[1]};
        } else if (left[1] != null) {
            return new TreeNode[]{root, left[1]};
        } else {
            return new TreeNode[]{root, root};
        }
    }
    

    方法三: 迭代算法

    分为两步: 第一步, 将左孩子接在当前节点右指针上, 这个简单。第二步, 将右孩子也要接在某个节点的右指针上, 这个节点该怎么找呢?其实就是当前节点的左子树一路向右的节点。

    public void flatten(TreeNode root) {
        TreeNode curr = root;
        while (curr != null) {
            if (curr.left != null) {
                // next表示当前节点的后继节点
                TreeNode next = curr.left;
                // predecessor表示当前节点右孩子的前驱节点
                TreeNode predecessor = next;
                while (predecessor.right != null) {
                    predecessor = predecessor.right;
                }
                // 将当前节点的右孩子, 连在其前驱节点上
                predecessor.right = curr.right;
                // 将当前节点的左孩子设为空
                curr.left = null;
                // 将当前节点的后继节点, 连在当前节点后面
                curr.right = next;
            }
            // 当前节点位置走向下一个位置
            curr = curr.right;
        }
    }
    
  • 相关阅读:
    ubuntu安装RabbitMQ
    pycharm中引入相对路径错误
    python之pip
    ubuntu安装django
    ubuntu16安装python3.7
    ubuntu上用源码进行一键安装mysql
    tar命令
    linux之bc命令
    linux源码安装
    ubuntu安装搜狗输入法后无法使用goland的快捷键 ctrl+alt+B
  • 原文地址:https://www.cnblogs.com/chenrj97/p/14290740.html
Copyright © 2011-2022 走看看