题目描述
【leetcode】114. 二叉树展开为链表( Flatten Binary Tree to Linked List)
给定一个二叉树,原地将它展开为链表。
例如,给定二叉树
1
/ \
2 5
/ \ \
3 4 6
将其展开为:
1
\
2
\
3
\
4
\
5
\
6
第一次解答
思路
递归,该方法的主要思想是从叶子结点开始,把右子树连接到左子树的末尾,自底向上,保证每向上一层,下面的结点都已经展平。展开一棵根节点为root的二叉树可划分为如下子问题:
- 展开root的右子树
- 展开root的左子树
- 找到root的左子树的最后一个结点,将该结点的右孩子指向root的右子树
- 将root的右孩子指向root的左孩子
- 将root的左孩子指向空
- 递归的进行上面1-5步,直到树展平。
上述过程中,为了突出主要思路,忽略了许多细节,如指针是否为空的判断,停止条件等,详情见代码。
test case:
[1,2,5,3,4,null,6]
[]
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
// 展开一棵树,并返回树末尾结点指针
TreeNode* dfs(TreeNode *root){
if(nullptr == root)
return nullptr;
// 叶子结点,已经是展平的了,末尾结点为root
if(nullptr == root->left && nullptr == root->right)
return root;
// 非叶子结点,把左右两边展平,并返回末尾结点指针
TreeNode* right_end = dfs(root->right);
TreeNode* left_end = dfs(root->left);
// 若左子树不为空,则把展平后的右子树连接到展平后的左子树末端。
if(nullptr != left_end){
left_end->right = root->right;
root->right = root->left;
root->left = nullptr;
}
// 返回最末尾的结点指针
if(nullptr == right_end)
return left_end;
else
return right_end;
}
void flatten(TreeNode* root) {
dfs(root);
return;
}
};
结果:
第二次解答
思路
看到有人说递归也需要额外的空间,可以不需要递归完成递归这题,启发了我。
迭代方法。大体思想是不断地把右子树拼接到左子树的末尾,是一种自顶向下
的方法:
- 首先明确:根据题意,展开的链表的顺序与二叉树前序遍历的顺序相同。
- 从根节点出发,找到左子树前序遍历最后访问的结点p
- 将p的右孩子指向根节点的右子树
- 将根节点的右孩子指向根节点的左子树
- 将根节点的左孩子指向空
- 根节点向右步进一位,即root = root->right
- 重复迭代2-6步,直到root为空,则树展开完成
同样地,上述过程中,为了突出主要思路,忽略了许多细节,如指针是否为空的判断,停止条件等,详情见代码。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void flatten(TreeNode* root) {
// 从根节点出发
while(nullptr != root){
// 找到左子树的末尾结点
TreeNode *p = root->left;
while(nullptr != p){
if(nullptr != p->right) p = p->right;
else if(nullptr != p->left) p = p->left;
else break;
}
// 若左子树不为空,则把右子树连接到左子树末端
if(nullptr != p){
p->right = root->right;
root->right = root->left;
root->left = nullptr;
}
// 根节点向前步进一格
root = root->right;
}
return;
}
};
结果: