当前位置: 首页 > news >正文

Swift 解法详解:LeetCode 366《寻找二叉树的叶子节点》

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 代码拆解
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

这道题乍一看有点像是普通的二叉树遍历,但它其实是让我们把二叉树“分层剥离”。你可以想象一棵树,它的叶子节点最先掉落,掉光之后剩下的新叶子继续掉落,直到整棵树光秃秃的。我们要做的就是模拟这个过程,把每一轮掉落的叶子节点收集起来。

描述

题目要求:

  • 给定一棵二叉树,反复删除叶子节点。
  • 每一轮,收集当前所有叶子节点的值。
  • 输出一个二维数组,数组中的每一项表示某一轮被删除的叶子。

举个例子:

输入: 1/ \2   3/ \4   5输出: [[4,5,3],[2],[1]]

解释过程:

  • 第一轮叶子节点是 [4,5,3]
  • 第二轮叶子节点是 [2]
  • 第三轮叶子节点是 [1]

就好像一棵树的叶子一层层被风吹掉,直到只剩下树干。

题解答案

直觉上,我们可以模拟“每次删掉叶子”的过程,但实现起来会很麻烦,要反复扫描整个树。

更高效的做法是:把问题转换成“高度归类”

  • 对于树中的一个节点,它最终掉落的那一轮,其实就是它的“高度”。
  • 什么是高度?可以理解为“离最近叶子节点的距离”。
  • 比如叶子本身高度为 0,它的父节点高度为 1,以此类推。
  • 我们只需要遍历一次树,计算每个节点的高度,然后把它们归类到对应的桶里即可。

题解代码分析

下面是 Swift 的实现:

import Foundation// 定义二叉树节点
public class TreeNode {public var val: Intpublic var left: TreeNode?public var right: TreeNode?public init(_ val: Int) {self.val = valself.left = nilself.right = nil}
}class Solution {func findLeaves(_ root: TreeNode?) -> [[Int]] {var result = [[Int]]()// 递归函数:返回节点的高度@discardableResultfunc getHeight(_ node: TreeNode?) -> Int {guard let node = node else { return -1 }let leftHeight = getHeight(node.left)let rightHeight = getHeight(node.right)let height = max(leftHeight, rightHeight) + 1// 确保结果数组足够大if result.count <= height {result.append([Int]())}result[height].append(node.val)return height}_ = getHeight(root)return result}
}// MARK: - Demo 演示
let root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left?.left = TreeNode(4)
root.left?.right = TreeNode(5)let solution = Solution()
print(solution.findLeaves(root)) // 输出 [[4, 5, 3], [2], [1]]

代码拆解

  1. TreeNode 定义:标准的二叉树节点。

  2. getHeight 递归函数

    • 叶子节点返回高度 0。
    • 每往上一层,高度就 +1。
    • 最后通过高度,把节点值放进 result[height]
  3. 收集结果

    • 按照高度分组,相当于模拟了一轮一轮的“叶子掉落”。
    • result[0] 就是第一批掉落的叶子,result[1] 是第二批,以此类推。

示例测试及结果

运行 Demo,结果是:

[[4, 5, 3], [2], [1]]

再补充一些额外测试:

// 单节点树
let single = TreeNode(10)
print(solution.findLeaves(single)) 
// [[10]]// 完全二叉树
let root2 = TreeNode(1)
root2.left = TreeNode(2)
root2.right = TreeNode(3)
root2.left?.left = TreeNode(4)
root2.left?.right = TreeNode(5)
root2.right?.left = TreeNode(6)
root2.right?.right = TreeNode(7)
print(solution.findLeaves(root2)) 
// [[4, 5, 6, 7], [2, 3], [1]]

时间复杂度

  • 每个节点只遍历一次,所以是 O(n),其中 n 是节点数。

空间复杂度

  • 递归栈深度最坏是树的高度,平均情况 O(log n),最坏情况 O(n)(比如链表树)。
  • 结果数组的大小也是 O(n)

总结

这道题的关键点在于把“删除叶子”的动态过程,转化成“高度归类”的静态计算。

  • 直观方法:反复删叶子,效率低。
  • 优雅方法:计算高度,一次搞定。

这个技巧其实挺实用的,在现实里也有场景:

  • 比如在公司裁员,最底层的员工(叶子节点)最先被裁,裁完一批后再轮到中层,最后才是老板。
  • 或者树形结构的数据清理,比如清除文件系统时,往往要从最深的文件开始,一层层删除,避免空目录残留。
http://www.dtcms.com/a/356725.html

相关文章:

  • SOME/IP-SD中”服务器服务组播端点”、“客户端服务组播端点”与“IPv4组播选项的区分
  • 记录:HSD部署(未完成)
  • 如何编译和使用 tomcat-connectors-1.2.32 源码(连接 Apache 和 Tomcat)​附安装包下载
  • CD71.【C++ Dev】二叉树的三种非递归遍历方式
  • 4.渗透-.DOS命令(文件目录操作)
  • 响应式编程框架Reactor【3】
  • Rust Web框架Axum学习指南之响应和异常封装
  • 如何备份 TECNO 手机上的短信
  • 云手机的安全性如何?
  • 云手机技术中都有着哪些局限性?
  • 国际期货Level2分时Tick历史行情数据处理分析
  • 关于 etree 的解析
  • 【c++题解】经典题目:带修改的 LIS 问题——CF650D Zip-line
  • 【修复软件】【缺少dll、ocx】加载失败报错无法运行注册老软件崩溃解决修复任何软件等通用方法
  • 中文PDF解析工具测评与选型指南
  • MemoryVLA:让机器人拥有“记忆“的视觉-语言-动作模型
  • 第2.1节:AI大模型之GPT系列(GPT-3、GPT-4、GPT-5)
  • 深入解析Qt节点编辑器框架:高级特性与性能优化(四)
  • 性能测试-jmeter7-元件提取器
  • 达梦数据库-归档日志(一)
  • 达梦数据库-数据文件 (二)
  • 【ShiMetaPi M4-R1】上手:RK3568B2 |开源鸿蒙(OpenHarmony) 开发板上手指南
  • dm8_静默安装简单快速
  • 第一百零二章:AI的“未来电影制片厂CEO”:多模态系统落地项目实战(完整 AI 视频创作平台)
  • mongoDB学习(docker)
  • MYSQL速通(2/5)
  • 【开题答辩全过程】以 基于Spring Boot的网上家庭烹饪学习系统的设计与实现为例,包含答辩的问题和答案
  • 软考-系统架构设计师 办公自动化系统(OAS)详细讲解
  • LeetCode 完全背包 279. 完全平方数
  • 小程序版碰一碰发视频:源码搭建与定制化开发的源头技术解析