1. 程式人生 > >[LeetCode] Flatten Binary Tree to Linked List 將二叉樹展開成連結串列

[LeetCode] 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
Hints:

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

這道題要求把二叉樹展開成連結串列,根據展開後形成的連結串列的順序分析出是使用先序遍歷,那麼只要是數的遍歷就有遞迴和非遞迴的兩種方法來求解,這裡我們也用兩種方法來求解。首先來看遞迴版本的,思路是先利用DFS的思路找到最左子節點,然後回到其父節點,把其父節點和右子節點斷開,將原左子結點連上父節點的右子節點上,然後再把原右子節點連到新右子節點的右子節點上,然後再回到上一父節點做相同操作。程式碼如下:

解法一:

// Recursion
class Solution {
public:
    void flatten(TreeNode *root) {
        if (!root) return;
        if (root->left) flatten(root->left);
        if (root->right) flatten(root->right);
        TreeNode *tmp = root->right;
        root->right = root->left;
        root
->left = NULL; while (root->right) root = root->right; root->right = tmp; } };

例如,對於下面的二叉樹,上述演算法的變換的過程如下:

     1
    / \
   2   5
  / \   \
 3   4   6

     1
    / \
   2   5
    \   \
     3   6
      \    
       4

   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

下面我們再來看非迭代版本的實現,這個方法是從根節點開始出發,先檢測其左子結點是否存在,如存在則將根節點和其右子節點斷開,將左子結點及其後面所有結構一起連到原右子節點的位置,把原右子節點連到元左子結點最後面的右子節點之後。程式碼如下:

解法二:

// Non-recursion
class Solution {
public:
    void flatten(TreeNode *root) {
        TreeNode *cur = root;
        while (cur) {
            if (cur->left) {
                TreeNode *p = cur->left;
                while (p->right) p = p->right;
                p->right = cur->right;
                cur->right = cur->left;
                cur->left = NULL;
            }
            cur = cur->right;
        }
    }
};

例如,對於下面的二叉樹,上述演算法的變換的過程如下:

     1
    / \
   2   5
  / \   \
 3   4   6

   1
    \
     2
    / \
   3   4
        \
         5
          \
           6
           
   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6

前序迭代解法如下:

解法三:

class Solution {
public:
    void flatten(TreeNode* root) {
        if (!root) return;
        stack<TreeNode*> s;
        s.push(root);
        while (!s.empty()) {
            TreeNode *t = s.top(); s.pop();
            if (t->left) {
                TreeNode *r = t->left;
                while (r->right) r = r->right;
                r->right = t->right;
                t->right = t->left;
                t->left = NULL;
            }
            if (t->right) s.push(t->right);
        }
    }
};

此題還可以延伸到用中序,後序,層序的遍歷順序來展開原二叉樹,分別又有其對應的遞迴和非遞迴的方法,有興趣的童鞋可以自行實現。

參考資料: