面试经典 114. 二叉树展开为链表

  • 最近工作越来越难找,裁员越来越懂了,焦虑的睡不着,怎么办呢,只能刷面试题,卷死你们

  • 今天这个题目没刷过,我思考了半天才只能用暴力,后来苦思冥想才想出来简单的方法,废话不多说,上链接:https://leetcode.cn/problems/flatten-binary-tree-to-linked-list/description/?envType=study-plan-v2&envId=top-interview-150
    在这里插入图片描述

  • 做这个题目之前,首先你要知道两个知识点:

    • 什么是二叉树?
    • 什么是先序遍历?
  • 先回答第一个问题,什么是二叉树?这是一个数据结构,是一种常见的树状数据结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点,如上图。

  • 了解什么是二叉树,才能回答第二问题,什么是先序遍历?首先这是一种遍历整个二叉树的方法,先序遍历:按照左子树 -> 根节点 -> 右子树的顺序遍历二叉树

  • 好了,了解了这两个基础知识,现在就来解决这道题。

  • 这道题目的是让我们把一颗树转变成一个单向链表

  • 这不简单,最暴力的方法就是用数组,把先序遍历的节点都存储起来,然后再通过遍历数组把他们都连接在一起不就行了吗,代码如下:

func flatten(root *TreeNode)  {
    list := preorderTraversal(root)
    //遍历整个数组,将树变成单向链表
    for i := 1; i < len(list); i++ {
        prev, curr := list[i-1], list[i]
        prev.Left, prev.Right = nil, curr
    }
}//将节点按照先序遍历的方式存储到数组中
func preorderTraversal(root *TreeNode) []*TreeNode {
    list := []*TreeNode{}
    if root != nil {
        list = append(list, root)
        list = append(list, preorderTraversal(root.Left)...)
        list = append(list, preorderTraversal(root.Right)...)
    }
    return list
}
  • ok,运行倒是成功了,但是这个效率可太难了,面试的时候,遇到这个题,只用这种做法肯定不成,怎么办呢?
    在这里插入图片描述

  • 我仔细想了想有两个优化方向

    • 时间方面,我希望只遍历一遍整个树就能解决这个问题
    • 空间方面,我希望空间复杂度为o(1) 就能解决
  • 方向确定好了,怎么办呢?

  • 通过我聪明的脑瓜子,转了又转,我想到了

  • 先序遍历是 根 左 右,相当于每次右子树都在后面,那我们可以把右子树,放到左子树最右边那个节点下面,并且当前根节点根据需求改造就行。

  • 这么讲有点抽象,我们通过图来举例,假设如示例1:
    在这里插入图片描述

  • 如果 我们只关注 当前节点 1 的话,我们需要做三个操作

    • 找到左子树最右的节点
    • 将右子树放到左子树最右的节点的右边
    • ​将左子树放到当前节点的右边
  • 结果就如下图:
    在这里插入图片描述

  • 是不是发现突然好像解决了一大半了

  • ok,我们继续,运行到 2 节点,继续上面的三个操作,结果如下:
    在这里插入图片描述

  • 基本上,我们就变成了一个单向链表,剩下的节点就重复的遍历下去,直至结束

  • 代码如下:

func Solution114(root *TreeNode)  {
  //遍历整个二叉树
  for root != nil{
    //如果有左子树
    if root.Left != nil{
      //找到左子树的最右节点
      next := root.Left
      pre := next
      for pre.Right != nil{
        pre = pre.Right
      }
      //将原来的右子树接到左子树的最右节点
      pre.Right = root.Right
      root.Left, root.Right = nil, next
    }
    //继续下一个节点
    root = root.Right
  }
}
  • 这个解法给我想出来之后,我感觉我整个人都升华了,我感觉自己太棒了,奖励一个大鸡腿嘻嘻
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值