一、题目
给定一个二叉树,原地将它展开为链表。
二、思路及代码
根据题意,二叉树展开的链表的顺序就是二叉树前序遍历的结果。
思路一:
先求出二叉树的前序遍历序列,再转换为链表。
注意:
转换成的链表仍然是用树结构存储,就是存储在每个节点的右孩子处,而左孩子为空。
代码实现:
class Solution {
public void flatten(TreeNode root) {
if(root == null)
return;
LinkedList<TreeNode> list = new LinkedList<>();
preOrder(root, list);
TreeNode head = list.pop();
head.left = null;
while(!list.isEmpty()){
TreeNode temp = list.pop();
temp.left = null;
head.right = temp;
head = head.right;
}
}
public void preOrder(TreeNode root, LinkedList<TreeNode> list){
if(root == null)
return;
list.add(root);
preOrder(root.left, list);
preOrder(root.right, list);
}
}
思路二:
思路一实际上是利用队列作为辅助工具完成转换,我们也可以利用栈来完成转换。
前序遍历顺序为:根节点——》左子树——》右子树。所以在入栈时,先将左孩子入栈,再将右孩子入栈,这样的话先弹出的就是左孩子。
代码实现:
class Solution {
public void flatten(TreeNode root) {
if(root == null)
return;
LinkedList<TreeNode> stack = new LinkedList<>();
stack.push(root);
TreeNode head = new TreeNode(-1);;
while(!stack.isEmpty()){
TreeNode temp = stack.pop();
head.left = null;
head.right = temp;
// 先将右孩子入栈
if(temp.right != null)
stack.push(temp.right);
// 再将左孩子入栈
if(temp.left != null)
stack.push(temp.left);
head = head.right;
}
}
}
思路三:(递归)
假如有一棵二叉树:
1
/ \
2 3
转换为链表的过程如下:
-
根节点的右子树变成根节点的左子树的右子树;
1 / 2 \ 3
-
根节点的左子树变成根节点的右子树;
1 \ 2 \ 3
所以,对于任意一棵树,可以递归的完成该过程。假设左、右子树已经递归地转换成链表,则再进行上面两步,就可完成整棵树的转换,即
- 将右子树挂到左子树的右叶子上
- 再将整棵左子树挂到根节点的右边
代码如下:
class Solution {
public void flatten(TreeNode root) {
if(root == null)
return;
flatten(root.right);
flatten(root.left);
if(root.left != null){
TreeNode node = root.left;
// 找到左孩子的右叶子
while(node.right != null){
node = node.right;
}
node.right = root.right;// 将右子树挂到左子树的右叶子上
root.right = root.left;// 再将整棵左子树挂到根节点的右边
root.left = null;
}
}
}