题目描述
给你二叉树的根结点 root ,请你将它展开为一个单链表:
- 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
- 展开后的单链表应该与二叉树 先序遍历 顺序相同。
示例
题解
重塑与递归。
重塑解法
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public void flatten(TreeNode root) {
List<Integer> firstOrdes = new ArrayList<>();
// 将树按照先序排列
findFirst(root, firstOrdes);
int len = firstOrdes.size();
if (len == 0) {
return;
}
TreeNode ori = root;
// 根据先序排列,构建结果,注意清空左子树
for (int i = 1; i < len; i++) {
root.right = new TreeNode(firstOrdes.get(i));
// 注意清空左节点
root.left = null;
root = root.right;
}
root = ori;
}
/**
* 将树按照先序进行排列
*
* @param root 根节点
* @param firstOrdes 根节点的先序排列
*/
public void findFirst(TreeNode root, List<Integer> firstOrdes) {
if (root == null) {
return;
}
firstOrdes.add(root.val);
findFirst(root.left, firstOrdes);
findFirst(root.right, firstOrdes);
}
}
性能
递归解法
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public void flatten(TreeNode root) {
if (root == null) {
return;
}
// 将右子树暂存
TreeNode rightTmp = root.right;
// 将左子树进行递归处理
flatten(root.left);
// 将处理好的左子树放到根节点右边
root.right = root.left;
// 清空左子树
root.left = null;
// 将暂存的右子树进行递归处理
flatten(rightTmp);
// 寻找最右结点
while(root.right != null) {
root = root.right;
}
// 将处理好的右子树放在最右结点的右边
root.right = rightTmp;
}
}
性能
注意点
递归其实是分为三步:
- 首先将根节点的左子树变成链表
- 其次将根节点的右子树变成链表
- 最后将变成链表的右子树放在变成链表的左子树的最右边
这就是一个递归的过程,递归的一个非常重要的点就是:不去管函数的内部细节是如何处理的,我们只看其函数作用以及输入与输出。对于函数flatten来说:
函数作用:将一个二叉树,原地将它展开为链表
输入:树的根节点
输出:无