LeetCode | 114. 二叉树展开为链表

原题Medium):

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

  

  根据题意,原地展开的意思是,按照中序遍历的顺序(中左右)把二叉树的结点逐一放到树的右节点上。

 

思路:

  我们已经知道,展开为链表后各节点顺序就是二叉树中序遍历的顺序,那么于一个节点而言,展开后,原本在其左子树节点肯定在原本其右子树的前面,例如:

  其展开后节点2肯定在结点3前面。结果为:

  那么,用左节点取代右节点的位置,这于根结点而言,应该是没错的,是合乎顺序的,但是在这之前,我们肯定要考虑右节点的去向,我们可以以题目的例子为例:

 

 

   我们用左子树取代右子树,右子树暂时孤立,即:

 

  那么按照中序遍历的顺序(节点内的数字就代表中序遍历的顺序),这右子树应该落在哪里呢?显然,应该节点4的右节点上:

 

  而于根结点1而言,节点4是一个什么节点呢?我们能否根据特征找到这个节点然后把右子树接上去呢?其实我们要找的就是根节点的左子树的最右节点(节点4就是最右节点),按照中序遍历的顺序,这个最右节点就是在遍历到根节点之前的最后一个节点(就是说遍历完该节点后下一个被遍历的节点就是根节点),那么把右子树接到该最右节点的右子树上,就非常合理了。至于怎么找到它也非常容易,因为我们已经知道它是左子树的最右节点了。从左子树的第一个节点开始一直往其右节点遍历,直到右节点为空。

  再经历了上述的变换后,我们还没有解决问题,可以看到,虽然节点1的下的所有节点已经移动到右子树,但右子树里仍有不合题意的节点,显然需要我们进入右子节点,以节点2为根节点,继续考虑其左右子树的情况,进行类似的变换。可以得知,这是递归的思路,但实现的方法可以是递归,也可以不是递归。

 1 void flatten(TreeNode* root) {
 2     while (root != nullptr) {
 3         if (root->left != nullptr) {
 4             auto most_right = root->left; // 如果左子树不为空, 那么就先找到左子树的最右节点
 5             while (most_right->right != nullptr) most_right = most_right->right; // 找最右节点
 6             most_right->right = root->right; // 然后将跟的右孩子放到最右节点的右子树上
 7             root->right = root->left; // 这时候跟的右孩子可以释放, 因此我令左孩子放到右孩子上
 8             root->left = nullptr; // 将左孩子置为空
 9         }
10         root = root->right; // 继续下一个节点
11     }
12     return;
13 }

posted @ 2019-10-25 14:23  羽园原华  阅读(161)  评论(0编辑  收藏  举报