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:
今天因为论文的事情只做了这一道题,但是想得比较多,前两种方法自己想出来,最后一个借鉴了别人的方法,感觉最后一种实现起来最简洁。看leetcode的Run Time,三种方法在效率上倒是没有太大区别,都在70多ms。虽然递归实现比较好想,但是通常迭代实现效率会更高一些。
If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.
题意:
给一个二叉树,原址将它压成一个链表。根据例子来看是使用每个TreeNode的右孩子指针来实现这个链表。
仔细观察题目里给的例子,可以发现这其实就是一个先序遍历。最后要注意每个节点的左孩子指针最后都要置为NULL;
下面提供三种解题方法,思路或实现方法各有不同。
1、既然是先序遍历,而且是原址实现,实际就是不断地将每个节点的左右孩子交换位置。比如上边的例子:先将root节点的左右孩子(也就是2和5)交换位置,2节点来到了自己正确的位置,然后再将2节点的左右孩子交换位置,3节点没有孩子,然后将4节点放到3节点后边,然后是5节点,以此类推。
class Solution {
public:
TreeNode *p = NULL;
void flatten(TreeNode *root) {
if (NULL == root) return;
TreeNode *left = root->left;
TreeNode *right = root->right;
exchange(root);
}
//这里最终的顺序和先序遍历一致,这里为了实现原址实现,只要某个节点左孩子不为空就将左右孩子交换位置
//交换完成后再将左孩子(其实是右孩子交换过来的)接到后面
void exchange(TreeNode *root){
if (NULL != root){
TreeNode *left = root->left;
TreeNode *right = root->right;
if (NULL == left && NULL == right){
p = root;
}
else{
if (left){
root->left = right;
root->right = left;
exchange(root->right);
p->right = root->left;
root->left = NULL;
exchange(p->right);
}
else{
exchange(root->right);
}
}
}
}
};
2、和第一种思路不同,如果某个节点的左孩子不为空,直接把这个节点的左子树插入到该节点和它的右子树之间。下面是递归实现:
class Solution{
public:
void flatten(TreeNode *root){
if(NULL == root) return;
fla(root);
}
TreeNode *fla(TreeNode *root){//每次调用返回当前的最末节点,以便后边节点连接
<span style="white-space:pre"> </span>TreeNode *left = root->left;
TreeNode *right = root->right;
root->left = NULL;
if (NULL == left && NULL == right){
return root;
}
if(left){
root->right = left;
TreeNode *last = fla(left);
if(right){
last->right = right;
}
else{
return last;
}
}
return fla(right);
}
};
3、第二种思路的迭代实现(代码超级简洁):
class Solution{
public:
void flatten(TreeNode *root){
if(NULL == root) return;
while(root){
if(root->left){
TreeNode *p = root->left;
while(p->right)
p = p->right;
p->right = root->right;
root->right = root->left;
root->left = NULL;
}
root = root->right;
}
}
};
今天因为论文的事情只做了这一道题,但是想得比较多,前两种方法自己想出来,最后一个借鉴了别人的方法,感觉最后一种实现起来最简洁。看leetcode的Run Time,三种方法在效率上倒是没有太大区别,都在70多ms。虽然递归实现比较好想,但是通常迭代实现效率会更高一些。