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
算法一,前序递归遍历
维持一个prev指针,将当前结点,挂在prev的right上。
在leetcode上实际执行时间为16ms。
/**
* 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) {
TreeNode *prev = 0;
pre(root, prev);
}
void pre(TreeNode *root, TreeNode *&prev) {
if (!root) return;
if (prev)
prev->right = root;
prev = root;
TreeNode *right = root->right;
pre(root->left, prev);
pre(right, prev);
root->left = 0;
}
};
算法二,使用栈保存右孩子
前序遍历时,先访问根,再访问左子树,然后右了树。
先将右子树用栈保存起来,等处理完左子树后,再来处理右子树。
在leetcode上实际执行时间为22ms。
class Solution {
public:
void flatten(TreeNode* root) {
stack<TreeNode *> s;
while (root) {
if (root->right)
s.push(root->right);
if (root->left) {
root->right = root->left;
root->left = 0;
}
else if (!s.empty()) {
root->right = s.top();
s.pop();
}
root = root->right;
}
}
};
算法三,类似线索二叉树遍历
在访问左子树之前,先将右子树挂在左子树最右下的一个结点上。
这样,就不需要上面算法的栈来保存右子树指针。
感觉这个方法最适合本题目,因为题目要求in-place。即不需要辅助空间完成任务。
在leetcode上实际执行时间为12ms。
class Solution {
public:
void flatten(TreeNode* root) {
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 = 0;
}
root = root->right;
}
}
};