1. 题目
给定一个二叉树,原地将它展开为一个单链表。
例如,给定二叉树
1
/
2 5
/ \
3 4 6
将其展开为:
1
2
3
4
5
6
Related Topics 树 深度优先搜索
👍 676 👎 0
2. 题解
2.1 解法1: 使用递归 dfs
递归分为三步:
- 首先将根节点的左子树变成链表
- 其次将根节点的右子树变成链表
- 最后将变成链表的右子树放在变成链表的左子树的最右边
这就是一个递归的过程,递归的一个非常重要的点就是:不去管函数的内部细节是如何处理的,我们只看其函数作用以及输入与输出
对于函数flatten来说:
函数作用:将一个二叉树,原地将它展开为链表
输入:树的根节点
输出:无
/**
* 解法1: 使用递归 dfs
* 递归函数作用: 将以该节点为根的树展开为链表
* 输入 : 根节点
* 输出: 无
*/
class Solution {
public void flatten(TreeNode root) {
if (root == null) return;
// 展开左右子树
flatten(root.left);
flatten(root.right);
// 将左子树展开的结果链接到right位置
TreeNode temp = root.right;
root.right = root.left;
root.left = null;
while (root.right != null) {
root = root.right;
}
root.right = temp;
}
}
2.2 解法2: 非递归的前序遍历过程中将链表展开
在前序遍历的同时, 每次保存上一个遍历的节点,
然后指向当前遍历节点, 最后组成单链表
/**
* 解法2: 非递归的前序遍历过程中将链表展开
* 在前序遍历的同时, 每次保存上一个遍历的节点,
* 然后指向当前遍历节点, 最后组成单链表
*/
class Solution {
public void flatten(TreeNode root) {
if (root == null) return;
TreeNode pre = null;
Deque<TreeNode> stack = new ArrayDeque<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
if (pre != null) {
pre.right = cur;
pre.left = null;
}
pre = cur;
if (cur.right != null) {
stack.push(cur.right);
}
if (cur.left != null) {
stack.push(cur.left);
}
}
}
}
2.3 解法3: 先前序遍历保存节点顺序到 list, 再遍历list, 将节点变为单链表
class Solution {
public void flatten(TreeNode root) {
if (root == null) {
return;
}
List<TreeNode> list = new ArrayList<>();
preOrder(root, list);
TreeNode pre;
for (int i = 1; i < list.size(); i++) {
pre = list.get(i - 1);
pre.left = null;
pre.right = list.get(i);
}
}
public void preOrder(TreeNode root, List<TreeNode> list) {
if (root == null) {
return;
}
list.add(root);
preOrder(root.left, list);
preOrder(root.right, list);
}
}