【树】-Lc114-二叉树原地展开为链表(先序遍历)

写在前面

  最近想复习一下数据结构与算法相关的内容,找一些题来做一做。如有更好思路,欢迎指正。



一、场景描述

  给定一个二叉树,原地将它展开为单链表。展开后的单链表应该同样使用TreeNode,其中right 子指针指向链表中下一个结点,而左子指针始终为null。

例如,给定二叉树
    1
   / \
  2   5
 / \   \
3   4   6

将其展开为:
1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

二、具体步骤

1.环境说明

名称说明
IntelliJ IDEA2019.2

2.代码

以下为Java版本实现:

public class Lc114_flatten {

    public static void main(String[] args) {
        TreeNode n6 = new TreeNode(6);
        TreeNode n5 = new TreeNode(5);
        n5.right = n6;

        TreeNode n4 = new TreeNode(4);
        TreeNode n3 = new TreeNode(3);

        TreeNode n2 = new TreeNode(2);
        n2.left = n3;
        n3.right = n4;

        TreeNode root = new TreeNode(1);
        root.left = n2;
        root.right = n5;

        flatten(root);

        // 打印
        while (root != null) {
            System.out.println(root.val);
            root = root.right;
        }
    }

    /**
     * 思路:
     * 二叉树的展开为链表,顺序是先序遍历
     * 且右子树放在左子树的最右结点上
     *
     *     1
     *    / \
     *   2   5
     *  / \   \
     * 3   4   6
     *
     *
     * 1、将root根节点的右子树,插在左子树的最右节点的右子树上
     *     1
     *    /
     *   2
     *  / \
     * 3   4
     *      \
     *       5
     *        \
     *         6
     *
     * 2、将root根节点的左子树插在root的右子树上,设置root的左子树为空
     *        1
     *      /  \
     *   null   2
     *         / \
     *        3   4
     *             \
     *              5
     *               \
     *                6
     *
     * 3、将root变为root.right,继续下一轮循环,直到root为空
     *        1
     *       / \
     *   null   2
     *         /
     *        3
     *         \
     *          4
     *           \
     *            5
     *             \
     *              6
     *
     *        1
     *       / \
     *   null   2
     *        /  \
     *     null   3
     *             \
     *              4
     *               \
     *                5
     *                 \
     *                  6
     *    ...
     *
     * while循环(root!=null)
     * 如果 root.left=null, 则直接处理右子树 root = root.right
     * 否则
     *      首先找到左子树的最右结点,定义 pre = root.left, while(pre!=null) pre=pre.right,得到最右结点
     *      pre.right = root.right
     *      root.right = root.left
     *      root.left = null
     *
     *      进行下一次迭代处理,root = root.right
     *
     * @param root
     */
    private static void flatten(TreeNode root) {
        while (root != null) {
            // 无左子树,一直是链表就不需要处理了
            if (root.left == null) {
                root = root.right;
            } else {
                // 找左子树的最右结点
                TreeNode pre = root.left;
                while (pre.right != null) {
                    pre = pre.right;
                }

                // 将root根节点的右子树,插在左子树的最右节点的右子树上
                pre.right = root.right;
                // 将root根节点的左子树插在root的右子树上,设置root的左子树为空
                root.right = root.left;
                // 处理左节点
                root.left = null;
                // 继续下一轮
                root = root.right;
            }
        }
    }

    static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode(int val) {
            this.val = val;
        }
    }
}


写在后面

  如果本文内容对您有价值或者有启发的话,欢迎点赞、关注、评论和转发。您的反馈和陪伴将促进我们共同进步和成长。

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值