给定一个二叉树,原地将它展开为链表。
例如,给定二叉树
将其展开为:
这道题要求把二叉树展开成链表,根据展开后形成的链表的顺序分析出是使用先序遍历,那么只要是树的遍历就有递归和非递归的两种方法来求解,这里我们也用两种方法来求解。
首先来看递归版本的,思路是先利用DFS的思路找到最左子节点,然后回到其父节点,把其父节点和右子节点断开,将原左子结点连上父节点的右子节点上,然后再把原右子节点连到新右子节点的右子节点上,然后再回到上一父节点做相同操作。
// Recursion
class Solution {
public:
void flatten(TreeNode *root) {
if (!root) return;
if (root->left) flatten(root->left);
if (root->right) flatten(root->right);
TreeNode *tmp = root->right;
root->right = root->left;
root->left = NULL;
while (root->right) root = root->right;
root->right = tmp;
}
};
例如,对于下面的二叉树,上述算法的变换的过程如下:
下面我们再来看非迭代版本的实现,这个方法是从根节点开始出发,先检测其左子结点是否存在,如存在则将根节点和其右子节点断开,将左子结点及其后面所有结构一起连到原右子节点的位置,把原右子节点连到原左子结点最后面的右子节点之后。
// Non-recursion
class Solution {
public:
void flatten(TreeNode *root) {
TreeNode *cur = root;
while (cur) {
if (cur->left) {
TreeNode *p = cur->left;
while (p->right) p = p->right;
p->right = cur->right;
cur->right = cur->left;
cur->left = NULL;
}
cur = cur->right;
}
}
};
例如,对于下面的二叉树,上述算法的变换的过程如下:
将树的问题和链表插入问题结合。对于每个节点,寻找左子树的最右端,它应该是左子树前序遍历的最后一位,也就是生成链表中,右子树根节点的前一位。
void flatten(TreeNode* root) {
if (!root) {
return;
}
while (root) {
if (root -> left) {
TreeNode* temp = root -> left;
while (temp -> right) {
temp = temp -> right;
}
temp -> right = root -> right;
root -> right = root -> left;
root -> left = NULL;
}
root = root -> right;
}
}
python:reverse的前序遍历
def __init__(self):
self.prev = None
def flatten(self, root):
if not root:
return None
self.flatten(root.right)
self.flatten(root.left)
root.right = self.prev
root.left = None
self.prev = root