Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
前言
力扣第114题 二叉树展开为链表
如下所示:
给你二叉树的根结点 root
,请你将它展开为一个单链表:
- 展开后的单链表应该同样使用
TreeNode
,其中right
子指针指向链表中下一个结点,而左子指针始终为null
。 - 展开后的单链表应该与二叉树 先序遍历 顺序相同。
示例 1:
输入: root = [1,2,5,3,4,null,6]
输出: [1,null,2,null,3,null,4,null,5,null,6]
一、思路
先分析一下题目,题目的意思很简单:将树按照先序遍历转为链表。链表的元素由树节点 TreeNode
组成,每个 TreeNode
节点的左孩子都为 null
。
实现的步骤主要分为以下两个步骤:
- 使用
先序遍历
得到二叉树的排列顺序 - 再根据排列顺序,组成新的链表
但是为了效率考虑,我们可以在遍历各个节点的时候就生成一个新的链表(这并不是原地交换)。最后再将新链表赋值给原来的链表即可。
举个例子
此处以示例一中的 root = [1,2,5,3,4,null,6]
作为例子
- 先使用递归可以得到该二叉树的前序遍历结果
1 -> 2 -> 3 -> 4 -> 5 -> 6
,此时这个结果存储在一个新的二叉树中 - 然后我们将原根节点
root
指向遍历的结果即可 - 最终可以得到由
TreeNode
组成的链表如下图所示:
二、实现
实现代码
实现方式与思路中保持一致。不足的地方就是需要使用额外的空间来存储前序遍历的结果。
TreeNode ret = new TreeNode();
TreeNode head = ret;
public void flatten(TreeNode root) {
preDfs(root);
if (ret.right != null){
root.left = null;
root.right = ret.right.right;
}
}
/**
* 获得树前序便利的结果
*/
private void preDfs(TreeNode root){
if (root == null)
return;
head.right = new TreeNode(root.val);
head = head.right;
// 前序遍历:根左右
preDfs(root.left);
preDfs(root.right);
}
测试代码
public static void main(String[] args) {
TreeNode treeNode = new TreeNode(1,
new TreeNode(2, new TreeNode(3), new TreeNode(4)),
new TreeNode(5, null, new TreeNode(6)));
new Number114().flatten(treeNode);
System.out.println(treeNode);
}
结果
三、总结
我后面自己去看了以下官方的题解,发现官方题解三中的原地交换的方式真的是非常新颖。我觉得思路中最重要的就是:在遍历左孩子的时候,左孩子最右边的节点就是右孩子的前序节点。这种方式就是 Morris 中序遍历
,可以有效的将空间复杂度降为 O(1)
。
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~