Flatten Binary Tree to Linked List 题解
题目来源:https://leetcode.com/problems/
Description
Given a binary tree, flatten it to a linked list in-place.
Example
For example,
Given
1
/
2 5
/
3 4 6
The flattened tree should look like:
1
2
3
4
5
6
Hints:
If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.
Solution
class Solution {
private:
TreeNode* getTail(TreeNode *node) {
if (node -> left == NULL && node -> right == NULL) {
return node;
}
TreeNode *leftTail = node -> left;
TreeNode *rightTail = node -> right;
if (leftTail) {
leftTail = getTail(leftTail);
if (rightTail)
rightTail = getTail(rightTail);
if (rightTail) {
leftTail -> right = node -> right;
}
node -> right = node -> left;
node -> left = NULL;
return rightTail ? rightTail : leftTail;
}
return getTail(rightTail);
}
public:
void flatten(TreeNode* root) {
if (root)
getTail(root);
}
};
解题描述
这道题题意是,将一棵二叉树变成一个链表,树节点的right
指针代表链表节点的next
指针,并且要求链表元素顺序是二叉树的前序遍历。同时,要求必须原地操作,也就是只能使用指针操作构造链表,而不能申请额外空间。上面给出的做法是递归前序遍历的做法,不难理解,下面要介绍一种使用Morris遍历变种的办法,不需要使用递归也不需要使用栈来暂存节点,可以说在空间复杂度上做得很好:
class Solution {
public:
void flatten(TreeNode* root) {
TreeNode *curNode = root, *preNode = NULL;
while (curNode) {
if (curNode -> left) {
preNode = curNode -> left;
while (preNode -> right) // 找到左子树链表尾
preNode = preNode -> right;
//此时preNode为curNode左子树链表尾,将其下一节点指向右子树链表头
preNode -> right = curNode -> right;
//curNode是当前链表头,下一节点指向左子树链表头
curNode -> right = curNode -> left;
curNode -> left = NULL; // 将左子树指向空
}
// 链表指针向后移动,模拟递归前序遍历
curNode = curNode -> right;
}
}
};