面试知识库

114. 二叉树展开为链表#

现实映射:圣诞灯饰的魔法#

想象你有一串圣诞树造型的彩灯,每个分岔处都有两个小灯泡。现在你想把它改造成一条直线悬挂在屋檐下。要求所有灯泡必须保持原来的点亮顺序,且只能用右侧的挂钩连接。这就是我们今天要解决的算法问题!

圣诞灯饰示意图

问题描述#

题目目标#

LeetCode第114题要求:给定一个二叉树的根节点,原地将它展开为一个单链表,展开后的链表顺序应与二叉树的前序遍历顺序一致。所有节点的右子指针指向下一个节点,左子指针始终为null。

示例 1#

输入:

1
   / \
  2   5
 / \   \
3   4   6
text

输出:

1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6
text

说明: 把输入和输出放在一起看,会更容易直接抓住题目要求的变化。

补充说明#

  • 二叉树通常使用层序数组表示,null 表示该位置没有节点。

直觉解法:前序遍历+重建#

最直接的思路就像拆解圣诞灯饰:

  1. 先完整记录所有灯泡的位置(前序遍历)
  2. 按照顺序重新组装成链条

Java实现#

复杂度分析
时间复杂度:O(n)
空间复杂度:O(n)(递归栈+列表存储)

忍者解法:原地修改的奥义#

真正的忍者不需要额外空间!我们需要在遍历的同时完成链表重组,就像在拆解灯饰的过程中直接重新连接灯泡。

核心思想:寻找前驱节点#

在前序遍历中,每个节点的后继其实是其左子树的最右节点。抓住这个规律,我们可以:

  1. 当前节点有左子树时:

    • 找到左子树的最右节点(前驱节点)
    • 将当前节点的右子树接到前驱节点的右侧
    • 将左子树移到右侧,左指针置空
  2. 移动到右子节点,重复上述过程

关键步骤演示(以示例为例)#

Java实现#

复杂度分析
时间复杂度:O(n)(每个节点被访问两次)
空间复杂度:O(1)

解法对比#

方法时间复杂度空间复杂度修改方式
前序遍历+重建O(n)O(n)非原地
原地修改法O(n)O(1)原地

模式总结#

这道题体现了两个重要算法思想:

  1. 莫里斯遍历思想:通过修改树结构来实现O(1)空间遍历
  2. 链表重组技巧:寻找前驱节点的操作模式

这种模式可以扩展到:

  • 将二叉树展开为中序链表
  • 将二叉搜索树转换为循环双向链表
  • 其他需要原地修改树结构的问题

忍者心法#

真正的算法高手,就像优秀的工匠改造灯饰:

  1. 洞察结构:发现前驱节点的关键作用
  2. 精细操作:在遍历时同步完成结构调整
  3. 节约资源:用最少的空间完成最复杂的改造

记住:当题目要求原地修改时,往往需要找到当前结构的某种内在规律,通过巧妙的指针操作来达成目标。