Flatten Binary Tree to Linked List

https://oj.leetcode.com/problems/flatten-binary-tree-to-linked-list/

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

         1
        / \
       2   5
      / \   \
     3   4   6

 

The flattened tree should look like:

   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

click to show hints.

Hints:

If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.

解题思路:

这题是很靠思路的一题。看似很难,解决后再考虑也不复杂。看看上面的例子,能看出来,操作是一个递归的过程。就是把每个子树的左侧子树,放到当前右子树的上面。然后把之前的右子树接在现在右子树的最右侧节点的右边。这个操作是可以preorder,inorder,postorder任意的。

也就是说,原来的二叉树,第一步可以做下面任意一步。

先flatten根节点,也就是preorder

1

 \

   2

   / \

3     4

        \

          5

           \

             6

或者先flatten左子树,也就是inorder

            1

          /    \

        2       5

         \        \

           3       6

            \

              4

或者postorder。

下面代码是preorder的一个例子,可以调整

flatten(root.left);
flatten(root.right);

两行代码的顺序,最后处理的结果是一样的。

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public void flatten(TreeNode root) {
        if(root == null){
            return;
        }
        
        TreeNode right = root.right;
        if(root.left != null){
            root.right = root.left;
            root.left = null;
            TreeNode temp = root;
            //temp为root原左子树(现在右子树)的最右侧节点
            while(temp.right != null){
                temp = temp.right;
            }
            //将root原来的右子树接在temp的右侧
            temp.right = right;
        }
        flatten(root.left);
        flatten(root.right);
    }
}

 上面是一个递归的方法,下面考虑如何改为迭代。我们可以看到,如果preorder处理的话,根节点的左侧子树直接都被甩到右侧了,那么left==null。这样完全可以preorder处理,然后root=root.right,直到root == null。迭代的代码如下。

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public void flatten(TreeNode root) {
        //root===null的处理也可以省略
        if(root == null){
            return;
        }
        
        while(root != null){
            TreeNode right = root.right;
            if(root.left != null){
                root.right = root.left;
                root.left = null;
                TreeNode temp = root;
                //temp为root原左子树(现在右子树)的最右侧节点
                while(temp.right != null){
                    temp = temp.right;
                }
                //将root原来的右子树接在temp的右侧
                temp.right = right;
            }
            root = root.right;
        }
    }
}

这样我们可以看到,即便在preorder的递归方法下,flatten(root.left)的递归也是多余的,因为flatten完左子树,左子树一定是null的,直接回return。故代码可以间接为下面。

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public void flatten(TreeNode root) {
        if(root == null){
            return;
        }
        
        TreeNode right = root.right;
        if(root.left != null){
            root.right = root.left;
            root.left = null;
            TreeNode temp = root;
            while(temp.right != null){
                temp = temp.right;
            }
            temp.right = right;
        }
        // flatten(root.left);
        flatten(root.right);
    }
}

从上面画的图想,会更容易理解。postorder就不能省略。

这道题对递归的考察和传统的遍历不太一样,又很像,确实比较考察对递归理解的是否深刻。需要好好掌握。

转载于:https://www.cnblogs.com/NickyYe/p/4315810.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值