2019-06-10 15:51:58 +00:00
|
|
|
|
# [114. Flatten Binary Tree to Linked List](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/)
|
|
|
|
|
|
|
|
|
|
# 思路
|
|
|
|
|
要求把二叉树展开成链表,根据例子可以看到是先序遍历的顺序。
|
|
|
|
|
## 思路一
|
|
|
|
|
最容易想到的就是先序遍历一遍树。我们可以用一个全局的指针`list_last`记录当前链表的最后一个节点,每遍历到一个节点就将其接到`list_last`后面(右指针)。
|
|
|
|
|
|
2019-06-11 11:56:58 +00:00
|
|
|
|
## 思路二*
|
2019-06-10 15:51:58 +00:00
|
|
|
|
此题也可以直接递归来做。即如果root的左右子树都已经是被展开好的,那么只需要将左子树接在root的右边,再将右子树接在原来左子树的最下边就可以了,如下例。
|
|
|
|
|
```
|
|
|
|
|
1 1
|
|
|
|
|
/ \ \
|
|
|
|
|
2 5 ===> 2
|
|
|
|
|
\ \ \
|
|
|
|
|
3 6 3
|
|
|
|
|
\ \
|
|
|
|
|
4 4
|
|
|
|
|
\
|
|
|
|
|
5
|
|
|
|
|
\
|
|
|
|
|
6
|
|
|
|
|
```
|
|
|
|
|
|
2019-06-11 11:56:58 +00:00
|
|
|
|
## 思路三*
|
|
|
|
|
可以将思路二改成非递归版本。原理类似:当前工作指针p指向root,如果p有左子树,那么将其左子树接在p的右边,而原来的右子树接在左子树的最右下边节点,此为一次循环,然后工作指针p向右下移动一步,重复上述操作。下面举个例子:
|
|
|
|
|
```
|
|
|
|
|
原二叉树:
|
|
|
|
|
1
|
|
|
|
|
/ \
|
|
|
|
|
2 5
|
|
|
|
|
/ \ \
|
|
|
|
|
3 4 6
|
|
|
|
|
|
|
|
|
|
第一次工作指针p指向1,循环后:
|
|
|
|
|
1
|
|
|
|
|
\
|
|
|
|
|
2
|
|
|
|
|
/ \
|
|
|
|
|
3 4
|
|
|
|
|
\
|
|
|
|
|
5
|
|
|
|
|
\
|
|
|
|
|
6
|
|
|
|
|
|
|
|
|
|
第二次工作指针p指向2,循环后:
|
|
|
|
|
1
|
|
|
|
|
\
|
|
|
|
|
2
|
|
|
|
|
\
|
|
|
|
|
3
|
|
|
|
|
\
|
|
|
|
|
4
|
|
|
|
|
\
|
|
|
|
|
5
|
|
|
|
|
\
|
|
|
|
|
6
|
|
|
|
|
接下来每次循环p依次指向3、4、5、6,由于p没有左子树,所以不作任何操作。
|
|
|
|
|
```
|
|
|
|
|
|
2019-06-10 15:51:58 +00:00
|
|
|
|
# C++
|
|
|
|
|
## 思路一
|
|
|
|
|
``` C++
|
|
|
|
|
class Solution {
|
|
|
|
|
private:
|
|
|
|
|
TreeNode *list_last = NULL;
|
|
|
|
|
|
|
|
|
|
void helper(TreeNode *root){ // 先序遍历
|
|
|
|
|
if(root == NULL) return;
|
|
|
|
|
if(list_last != NULL) // 不是第一个
|
|
|
|
|
list_last -> right = root;
|
|
|
|
|
|
|
|
|
|
list_last = root;
|
|
|
|
|
|
|
|
|
|
// 由于后面要将左右指针置空,所以这里先记录一下
|
|
|
|
|
TreeNode *left = root -> left;
|
|
|
|
|
TreeNode *right = root -> right;
|
|
|
|
|
root -> left = NULL;
|
|
|
|
|
root -> right = NULL;
|
|
|
|
|
|
|
|
|
|
helper(left);
|
|
|
|
|
helper(right);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
void flatten(TreeNode* root) {
|
|
|
|
|
if(root == NULL) return;
|
|
|
|
|
list_last = NULL;
|
|
|
|
|
helper(root);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 思路二
|
|
|
|
|
``` C++
|
|
|
|
|
class Solution {
|
|
|
|
|
public:
|
|
|
|
|
void flatten(TreeNode* root) {
|
|
|
|
|
if(root == NULL) return; // 递归出口
|
|
|
|
|
flatten(root -> left);
|
|
|
|
|
flatten(root -> right);
|
|
|
|
|
|
|
|
|
|
TreeNode *right = root -> right; // 先备份右子树
|
|
|
|
|
root -> right = root -> left; // 将左子树放在右边
|
|
|
|
|
root -> left = NULL;
|
|
|
|
|
|
|
|
|
|
TreeNode *tmp = root;
|
|
|
|
|
// 一路下降到最下面
|
|
|
|
|
while(tmp -> right) tmp = tmp -> right;
|
|
|
|
|
tmp -> right = right;
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-06-11 11:56:58 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 思路三
|
|
|
|
|
``` C++
|
|
|
|
|
class Solution {
|
|
|
|
|
public:
|
|
|
|
|
void flatten(TreeNode* root) {
|
|
|
|
|
TreeNode *p = root;
|
|
|
|
|
while(p){
|
|
|
|
|
if(p -> left){
|
|
|
|
|
// 先备份右子树
|
|
|
|
|
TreeNode *right_bk = p -> right;
|
|
|
|
|
p -> right = p -> left;
|
|
|
|
|
p -> left = NULL;
|
|
|
|
|
TreeNode *tmp = p;
|
|
|
|
|
while(tmp -> right) tmp = tmp -> right;
|
|
|
|
|
// 此时tmp指向p原来左子树的最右下节点
|
|
|
|
|
tmp -> right = right_bk;
|
|
|
|
|
}
|
|
|
|
|
p = p -> right;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-06-10 15:51:58 +00:00
|
|
|
|
```
|