LeetCode力扣第114题:多种算法实现 将二叉树展开为链表

2024-05-10 01:36

本文主要是介绍LeetCode力扣第114题:多种算法实现 将二叉树展开为链表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
python源码解读
程序员必备的数学知识与应用

题目描述

给定一个二叉树,原地将它展开为一个单链表。例如,给定二叉树:

    1/ \2   5/ \   \
3   4   6

展开后应该变为:

1\2\3\4\5\6

方法一:递归展开

解题步骤

  1. 如果树为空,直接返回。
  2. 递归展开左子树和右子树。
  3. 将左子树插入到右子树的位置。
  4. 将原来的右子树接到当前右子树的末端。
  5. 考虑到展开后没有左子节点,将左子节点设置为None

代码示例

class Solution:def flatten(self, root):if not root:returnself.flatten(root.left)self.flatten(root.right)# 左右子树已经被拉平成一条链表left = root.leftright = root.right# 将左子树作为右子树root.left = Noneroot.right = left# 找到当前右子树(原左子树)的末端并连接原右子树p = rootwhile p.right:p = p.rightp.right = right

方法一的改进主要可以从两个方面进行:优化递归效率和空间使用。虽然基本递归方法简单直观,但它可能导致不必要的栈空间消耗,尤其是在处理非常深的树时可能会导致栈溢出。以下是几种改进策略:

改进1: 尾递归优化

虽然Python默认不支持尾递归优化,但我们可以尽可能减少递归中不必要的操作,将必要的操作移至递归调用之前执行,减少递归调用栈的深度。

改进代码示例

class Solution:def flatten(self, root):def flattenTree(node):if not node:return None# 如果节点是叶子节点,直接返回if not node.left and not node.right:return node# 递归平展左子树leftTail = flattenTree(node.left)rightTail = flattenTree(node.right)# 将左子树插入到右子树的地方if leftTail:leftTail.right = node.rightnode.right = node.leftnode.left = None# 返回最后的尾部节点return rightTail if rightTail else leftTailflattenTree(root)
改进2: 减少递归深度

尽可能地在每个节点处理完毕后立即释放其左子树的引用,减少Python垃圾回收器的压力,并减少递归深度。

改进代码示例

class Solution:def flatten(self, root):# Helper function to perform flatten operationdef flattenNode(node):if not node:return None# Flatten the left and right subtreeleft_last = flattenNode(node.left)right_last = flattenNode(node.right)# If there is a left subtree, weave it into the right subtreeif left_last:left_last.right = node.rightnode.right = node.leftnode.left = None# The rightmost node is needed for linking to the parent node's right subtreereturn right_last if right_last else left_lastflattenNode(root)

方法二:迭代展开

解题步骤

  1. 使用栈来辅助迭代过程。
  2. 每次取出栈顶元素,如果有右子节点先压栈,再压左子节点。
  3. 修改每个节点的右指针指向下一个栈顶元素,左指针设置为None

代码示例

class Solution:def flatten(self, root):if not root:returnstack = [root]prev = Nonewhile stack:curr = stack.pop()if prev:prev.right = currprev.left = Noneif curr.right:stack.append(curr.right)if curr.left:stack.append(curr.left)prev = curr

方法三:寻找前驱节点

解题步骤

  1. 对于每个节点,如果左子节点不为空,找到左子树的最右节点(前驱节点)。
  2. 将原右子树接到前驱节点的右边。
  3. 将左子树移到右边,左子树置为空。
  4. 继续处理链表中的下一个节点。

代码示例

class Solution:def flatten(self, root):curr = rootwhile curr:if curr.left:pre = curr.leftwhile pre.right:pre = pre.rightpre.right = curr.rightcurr.right = curr.leftcurr.left = Nonecurr = curr.right

算法分析

  • 时间复杂度
    • 递归展开:(O(n)),每个节点访问一次。
    • 迭代展开:(O(n)),每个节点访问一次。
    • 寻找前驱节点:(O(n)),每个节点访问一次。
  • 空间复杂度
    • 递归展开:(O(n)),递归栈的空间。
    • 迭代展开:(O(n)),使用了额外的栈。
    • 寻找前驱节点:(O(1)),原地修改,不需要额外空间。

优劣势对比

  • 递归展开
    • 优点:实现简单直观。
    • 缺点:需要额外的栈空间来处理递归。
  • 迭代展开
    • 优点:避免了递归可能导致的栈溢出。
    • 缺点:需要使用栈来存储节点。
  • 寻找前驱节点
    • 优点:不需要额外空间,空间复杂度最优。
    • 缺点:代码逻辑相对复杂,需要处理更多的指针操作。

应用示例

这种技巧在处理需要将树结构线性化处理的场景非常有用,例如在图形界面开发中,需要按特定顺序访问或显示节点信息,或者在需要频繁查找、更新结点而又不频繁修改树结构的数据库和文件系统中。

这篇关于LeetCode力扣第114题:多种算法实现 将二叉树展开为链表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/975065

相关文章

字符串处理函数strchr和strstr的实现

1,strchr函数 函数功能:查找一个字符。在一个字符串中查找一个特定的字符。 函数原型:char *strchr(char const *str,int ch); 函数说明:strchr在字符串str中查找字符ch第一次出现的位置,找到后返回一个指向该位置的指针。如果该字符不存在于字符串中,则返回一个NULL指针。注意:第二个参数是一个整型值,但是,它包含了一个字符串值。

Android图片轮播的实现总结

前言: 在很多app中,我们都可以看到几张图片每隔一段时间就切换一下,这就是我们所称的图片轮播的功能,其主要实现就是用到了ViewPager, 下面我们来着重讲解一下其具体实现 效果图: 步骤一:在XML中添加ViewPager控件 比如: <?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:a

Anddroid 适配多种屏幕

Android 运行在各种不同尺寸和屏幕密度的设备上。对于应用来说,Android系统提供了一个稳定的开发环境,然后在 调整应用界面显示的问题上也花了很多的功夫。与此同时,为了能够在不同配置的屏幕上去优化你的UI设计,Android 系统也提供相应的APIs以允许你对于特定尺寸和密度的屏幕进行控制。比如说,你想要你的UI去适配平板,而不是手机。 尽管Android系统可以对你的应用进行

SpringMVC+Hibernate +MySql+ EasyUI实现CRUD

SpringMVC+Hibernate +MySql+ EasyUI实现CRUD 原文地址 http://my.oschina.net/xshuai/blog/345117

【百度语音识别】JavaAPI方式语音识别示例 MP3转PCM文件Java实现

【百度语音识别】JavaAPI方式语音识别示例MP3转PCM Java-API合成语音示例:http://ai.baidu.com/forum/topic/show/496727REST-API文档地址:http://ai.baidu.com/docs#/TTS-API/top注意:需要下载MP3插件jar。才可以进行MP3CONVERTPCM 链接: https://pan.baidu.c

高德地图实现多天路线规划(途经点显示自定义内容)+轨迹回放(显示车牌)

​​​​​​​  联系作者Q/V:783021975 Tips: 1.高德地图最多支持16个途径点,如果超过可以进行数据优化,或进行数据再次拆分进行规划 2023年6月20日更新 如果遇到 获取驾车数据失败 :INVALID_USER_SCODE 请确保是否按官方文档要求的配置了安全密钥 准备-入门-教程-地图 JS API | 高德地图API 引入地图 JSAPI 脚本之前增加设置 JSAP

Jquery 实现表单提交按钮变灰,防止多次点击提交重复数据

表单提交时候我们应该控制提交按钮,不能点击多次进行数据的重复提交。要不然就会有冗余的重复的数据在系统中,造成系统出现数据垃圾。jQuery很简单的就可以实现对表单提交按钮控制,下面就是相关的例子和代码。 <form action="${pageContext.servletContext.contextPath}/XXX/###" method="post" id="messag

Spring AOP 实现监控方法执行的时间(统计service中方法执行的时间)

项目中有时候会遇到统计方法执行的时间,来对项目进行优化!下面是我自己在工作中遇到的问题,和我自己的解决方法。 要统计出项目中方法执行时间大于1秒的那些方法!我们的项目开发使用的是SpringMVC 那么首先想到使用 Aop Aspet 切面统计,那样子更加方便也高效。 1:打开切面!因为项目使用的SpringMVC,项目中的配置文件就配置的 <aop:aspectj-autoproxy pro

重试机制实现方案

大家好,我是阿飞云 怕什么真理无穷,进一步有近一步的欢喜 本文内容是目前团队内小磊同学对重试机制实现方案的梳理总结。 从为什么需要重试的背景开始,到重试的场景,大致的一些设计思路,最后通过两个成熟的retry组件进行案例讲解,理论+实战。 背景 重试是系统提高容错能力的一种手段。在一次请求中,往往需要经过多个服务之间的调用,由于网络波动或者其他原因,请求可能无法正常到达服务端或者服务端的请

C:单链表的简单实现

前言 今天整理资料的时候翻出来的文件,发现是以前学习数据结构的时候写的代码,当初是看郝凯老师的视频学习的C语言的数据结构,下面是对于一个单链表的简单的实现。 /*******************************************************************************@file SingleLinker.c*@version V1.0