二叉树展开为链表

题目描述:

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

例如,给定二叉树

    1
/ \
2 5
/ \ \
3 4 6

将其展开为:

1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

  

解法一

我们需要两步完成这道题。

  • 将左子树插入到右子树的地方
  • 将原来的右子树接到左子树的最右边节点

考虑新的右子树的根节点,一直重复上边的过程,直到新的右子树为 null

过程如下展示

 1
   / \
  2   5
 / \   \
3   4   6

//将 1 的左子树插入到右子树的地方
    1
     \
      2         5
     / \         \
    3   4         6        
//将原来的右子树接到左子树的最右边节点
    1
     \
      2          
     / \          
    3   4  
         \
          5
           \
            6
            
 //将 2 的左子树插入到右子树的地方
    1
     \
      2          
       \          
        3       4  
                 \
                  5
                   \
                    6   
        
 //将原来的右子树接到左子树的最右边节点
    1
     \
      2          
       \          
        3      
         \
          4  
           \
            5
             \
              6 

 

//go
func flatten(root *TreeNode)  {
    for root != nil {
        if root.Left == nil {
            root = root.Right
        }else {
            pre := root.Left
            for pre.Right != nil {
                pre = pre.Right
            }
            pre.Right = root.Right
            root.Right = root.Left
            root.Left = nil
            root = root.Right
        }
    }
}

  

方法二

先序遍历为1-2-3-4-5-6,如果按照先序遍历执行,1的左孩子为nil,右孩子为2,但是5就没了。所以不能直接使用先序遍历。

但是我们可以逆先序遍历:6-5-4-3-2-1

然后每遍历一个节点就将当前节点的右指针更新为上一个节点。

遍历到 5,把 5 的右指针指向 6。6 <- 5 4 3 2 1。

遍历到 4,把 4 的右指针指向 5。6 <- 5 <- 4 3 2 1。

……

(这个思想打个比方就像接链条,我们先把尾部的接好,在往头部拼接,整体就串起来了)

//go
func flatten(root *TreeNode)  {
 if root==nil{
  return
 }
 var pre *TreeNode
 //使用2重指针
 dfs(root,pre)
}

func dfs(root *TreeNode,pre *TreeNode){
 if root==nil{
  return
 }
 dfs(root.Right,pre)
 dfs(root.Left,pre)
 root.Right= pre
 root.Left=nil
 pre =root
}

  地址:https://mp.weixin.qq.com/s/4PNuVEgXJpCWgzVl35eQ2g

posted @ 2020-08-07 09:31  small_lei_it  阅读(100)  评论(0编辑  收藏  举报