Leetcode——利用先序遍历特性完成114. 二叉树展开为链表

题目:114. 二叉树展开为链表
这道题很有意思,因为评论区各种递归实在看不懂过,直到看到一条利用二叉树特性的完成的评论,就自己模仿完成,就记录并分享一下。

思路一:重新建树

思路:用链表记录所有的节点,然后设置。这里一定要保存节点,因为这道题要求修改原来的root,而不是创建新的节点。

public void flatten(TreeNode root) {
     //先序遍历+建树
        if(root==null) return ;
        List<TreeNode> buildList = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
//        先序中 左右,所以入栈中 右左
        //因为中是先处理的
        while (!stack.isEmpty()) {
            TreeNode pop = stack.pop();
            buildList.add(pop);
            if (pop.right != null) {
                stack.push(pop.right);
            }
            if (pop.left != null) {
                stack.push(pop.left);
            }
        }
        for (int i = 0; i < buildList.size()-1; i++) {
            buildList.get(i).left=null;
            buildList.get(i).right=buildList.get(i+1);
        }
        buildList.get(buildList.size()-1).left=null;
        buildList.get(buildList.size()-1).right=null;
    }

在这里插入图片描述

思路二:利用先序遍历的特性

上面那种方法需要额外空间,这种空间复杂度为O(1)
在这里插入图片描述
思路:将当前的左子树接到右边去,那么首先要找到的左子树、然后找到右子树的前驱节点,把右子树接到前驱,再把左子树整体移到右子树上。
听起来有点绕,来个例子,cur表示当前处理的节点,right_pre表示cur右子树的前驱
以实例中的图为例,从根节点开始

  1. cur = 1
    找到cur.left的最右节点right_pre,也就是4,然后把cur.right 接到right_pre后面。再把cur.left接到cur的右边
    处理完了之后:
    在这里插入图片描述
    然后cur = cur.right,为什么能放心大胆地这么做,因为cur左边的都被移到右边了,并且是按照先序遍历移动的,所以直接找右边就可以。

  2. cur=2
    将4 接到 3 后面,3 再接到2后面,就能得到
    在这里插入图片描述

但是还是要继续去右边找,看有没有未处理的左子。

代码:

public void flatten(TreeNode root) {
       TreeNode cur = root;
        while ( cur!=null ){
            //先序表里,找到当前节点的下一个节点
            TreeNode right_pre = cur.left;
            //找到cur.right的前一个,也就是左子树的最右节点
            while (right_pre!=null && right_pre.right != null ){
                right_pre = right_pre.right;
            }
            //拼接操作
            if(right_pre!=null){
                right_pre.right=cur.right;
                //再把左边整个接到右边
                cur.right=cur.left;
                cur.left=null;
            }
            //继续寻找下一个
            cur = cur.right;
        }
    }

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值