1. 程式人生 > 實用技巧 >二叉樹展開為連結串列

二叉樹展開為連結串列

題目描述:

給定一個二叉樹,原地將它展開為一個單鏈表。

例如,給定二叉樹

    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