算法小知识-----04.11-----二叉树展开为链表

115 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

周一,戴上我的痛苦面具

二叉树展开为链表

该题出自力扣的114题 —— 二叉树展开为链表【中等】

审题

给你二叉树的根结点 root ,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
展开后的单链表应该与二叉树 先序遍历 顺序相同。

image.png

  • 该题的题意也十分简单,就是给出一个二叉树,需要把它展开成为一个链表
  • 首先,展开成为链表,需要使这个二叉树成为线性,也就是全部整合到右节点
    • 第一步,把整个右子树移动到左子树的最右节点
    • 第二步,再把整个左子树移动到右子树
    • 左子树置空
    • 重复一二步
  • 利用代码去实现该逻辑也好说
    • while,当前节点不为空时循环
    • 重复上述步骤即可
  • 除此以外还可以利用递归的方式,而且做到空间复杂度为O(1),也就是不额外开辟新的空间去装载二叉树,毕竟开辟空间的话,方法很多,枚举存储节点+重新排序等
  • 更多说的是直接在原来的节点上改变指向,空间复杂度并没有要求。
  • 如果利用先序遍历的话,直接把当前节点指向上一节点的右节点,虽然看起来能行得通,但是实际操作会导致上一节点的原右节点丢失
  • 所以可以利用逆后序方法
    • 后序遍历:左右中
    • 逆后序遍历:右左中
  • 每遍历一个节点,就把当前节点的右节点指向上一节点即可

编码

  • 非递归实现
class Solution {
     private TreeNode pre = null;
     public void flatten(TreeNode root) {
         while (root != null){
             if (root.left == null){
                 root = root.right;
             }else {
                 TreeNode pre = root.left;
                 while (pre.right != null){
                     pre = pre.right;
                 }
                 pre.right = root.right;
                 root.right = root.left;
                 root.left = null;
                 root = root.right;
             }
         }
     }
}
  • 递归实现
class Solution {
     private TreeNode pre = null;
     public void flatten(TreeNode root) {
     if (root == null)
         return;
     flatten(root.right);
     flatten(root.left);
     root.right = pre;
     root.left = null;
     pre = root;
     }
 }

image.png