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
Hints:
If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.
上面是題目及提示信息,大概意思是要按照前序遍歷的順序,將其變成一個但鏈表(但還是用樹結構存),OK,開始分析下:
按照題目要求,它要把左子樹的所有節點按照前序的順序,掛載在右子樹的鏈表中,那么我們首先遇到的第一個問題,把左子樹掛載在右邊,那之前的跟節點的右子樹怎么處理?
上面這個問題,可以這樣思考,我們假設已經把左子樹掛載在右邊,先忽視之前根節點的右子樹,那么現在需要把其加載進去,那顯然按照前序遍歷的思想,我們肯定是把右子樹掛載在左子樹前序遍歷的最后一個元素中,OK,這是我們目前的想法。
再思考下,我們只是簡單的將根節點的左子樹掛載在它和它的右子樹中間,並沒有將其“捋平”,這樣就涉及到遞歸的處理,反復的將其,加進去。那這樣就涉及到剛開始的一個問題,我們是否真的需要把右子樹擱在左子樹前序遍歷的最后一個元素中?如下圖所示,這里顯然,我們只需要將4 擱在2的右子樹位置上,(第二張圖),然后再遞歸的捋順根節點的right即可
1 1
2 4 2
3 5 6 3 4
5 6
因此,我們可以寫出以下代碼:
public void flatten(TreeNode root) { if (root == null) return; if (root.left != null) { TreeNode cur = root.left; while (cur.right != null) { cur = cur.right; } cur.right = root.right; root.right = root.left; root.left = null; } flatten(root.right); }
我們可以發現,最后的遞歸,特別像循環,因此可以消遞歸,優化代碼,如下
public void flatten(TreeNode root) { while(root != null){ if(root.left != null){ TreeNode cur = root.left; while(cur.right != null){ cur = cur.right; } cur.right = root.right; root.right = root.left; root.left = null; } root = root.right; } }