LeetCode(114): 二叉樹展開為鏈表


Medium!

題目描述:

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

例如,給定二叉樹

    1
   / \
  2   5
 / \   \
3   4   6

將其展開為:

1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

解題思路:

這道題要求把二叉樹展開成鏈表,根據展開后形成的鏈表的順序分析出是使用先序遍歷,那么只要是數的遍歷就有遞歸和非遞歸的兩種方法來求解,這里我們也用兩種方法來求解。

首先來看遞歸版本的,思路是先利用DFS的思路找到最左子節點,然后回到其父節點,把其父節點和右子節點斷開,將原左子結點連上父節點的右子節點上,然后再把原右子節點連到新右子節點的右子節點上,然后再回到上一父節點做相同操作。

C++解法一:

 1 // Recursion
 2 class Solution {
 3 public:
 4     void flatten(TreeNode *root) {
 5         if (!root) return;
 6         if (root->left) flatten(root->left);
 7         if (root->right) flatten(root->right);
 8         TreeNode *tmp = root->right;
 9         root->right = root->left;
10         root->left = NULL;
11         while (root->right) root = root->right;
12         root->right = tmp;
13     }
14 };

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

復制代碼
     1
    / \
   2   5
  / \   \
 3   4   6

     1
    / \
   2   5
    \   \
     3   6
      \    
       4

   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6
復制代碼

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

C++解法二:

 1 // Non-recursion
 2 class Solution {
 3 public:
 4     void flatten(TreeNode *root) {
 5         TreeNode *cur = root;
 6         while (cur) {
 7             if (cur->left) {
 8                 TreeNode *p = cur->left;
 9                 while (p->right) p = p->right;
10                 p->right = cur->right;
11                 cur->right = cur->left;
12                 cur->left = NULL;
13             }
14             cur = cur->right;
15         }
16     }
17 };

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

復制代碼
     1
    / \
   2   5
  / \   \
 3   4   6

   1
    \
     2
    / \
   3   4
        \
         5
          \
           6
           
   1
    \
     2
      \
       3
        \
         4
          \
           5
            \
             6
復制代碼

前序迭代解法如下:

C++解法三:

 1 class Solution {
 2 public:
 3     void flatten(TreeNode* root) {
 4         if (!root) return;
 5         stack<TreeNode*> s;
 6         s.push(root);
 7         while (!s.empty()) {
 8             TreeNode *t = s.top(); s.pop();
 9             if (t->left) {
10                 TreeNode *r = t->left;
11                 while (r->right) r = r->right;
12                 r->right = t->right;
13                 t->right = t->left;
14                 t->left = NULL;
15             }
16             if (t->right) s.push(t->right);
17         }
18     }
19 };

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM