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

LeetCode 385 迷你语法分析器 Swift 题解:从字符串到嵌套数据结构的解析过程

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

文章目录

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

摘要

在日常开发中,我们经常会遇到需要解析字符串的场景,比如配置文件、日志格式,甚至是网络传输中的 JSON 数据。这道题就类似于一个“小型 JSON 解析器”,给定一个描述嵌套列表的字符串,要求我们把它还原成嵌套的数据结构 NestedInteger

本文会从题目描述入手,逐步分析如何用栈的方式来解析字符串,并给出 Swift 的完整解法与运行示例。最后,我们也会结合实际场景聊聊这个题目背后的工程意义。

描述

题目的输入是一个字符串 s,它可能是:

  1. 单个整数,比如 "324"
  2. 一个嵌套的整数列表,比如 "[123,[456,[789]]]"

目标是返回一个 NestedInteger 对象。这个类已经预定义好,支持以下操作:

  • isInteger():判断是否是单个整数。
  • getInteger():获取整数值。
  • getList():获取嵌套列表。
  • add(_ elem: NestedInteger):往列表里添加一个元素。

换句话说,我们要写一个语法分析器,把字符串转换成 NestedInteger

题解答案

常见的解析方法有两种:

  1. 递归法:遇到 [ 就递归解析子列表,遇到 ] 就返回。
  2. 栈法:遍历字符串,遇到 [ 就新建一个列表对象压栈,遇到 ] 就出栈并加入上层。

这里我们采用 栈法,因为更直观,也更接近手动实现一个 JSON 解析器的过程。

题解代码分析

完整 Swift 实现如下:

import Foundation// 模拟 LeetCode 提供的 NestedInteger 类
class NestedInteger {private var integer: Int?private var list: [NestedInteger] = []init() {}init(_ value: Int) {self.integer = value}func isInteger() -> Bool {return integer != nil}func getInteger() -> Int? {return integer}func setInteger(_ value: Int) {self.integer = value}func add(_ elem: NestedInteger) {list.append(elem)}func getList() -> [NestedInteger] {return list}// 方便打印调试func toString() -> String {if let value = integer {return "\(value)"} else {return "[" + list.map { $0.toString() }.joined(separator: ",") + "]"}}
}class Solution {func deserialize(_ s: String) -> NestedInteger {// 如果输入是单个整数,直接返回if let value = Int(s) {return NestedInteger(value)}var stack: [NestedInteger] = []var numBuffer = ""var negative = falsevar current: NestedInteger? = nilfor char in s {if char == "[" {let ni = NestedInteger()if let top = stack.last {top.add(ni)}stack.append(ni)} else if char == "]" {if !numBuffer.isEmpty {let num = (negative ? -1 : 1) * Int(numBuffer)!stack.last?.add(NestedInteger(num))numBuffer = ""negative = false}current = stack.popLast()} else if char == "," {if !numBuffer.isEmpty {let num = (negative ? -1 : 1) * Int(numBuffer)!stack.last?.add(NestedInteger(num))numBuffer = ""negative = false}} else if char == "-" {negative = true} else if char.isNumber {numBuffer.append(char)}}return current!}
}

代码解析

  1. NestedInteger:我们自己实现一个简化版,方便测试。

  2. deserialize() 方法

    • 如果整个字符串是单个整数,直接返回。

    • 用栈来保存当前的嵌套结构。

    • 遍历字符串:

      • 遇到 [:新建一个列表对象,压入栈。
      • 遇到数字或 -:存入缓冲区,等到完整数字解析完成再入栈。
      • 遇到 ,]:把缓冲区里的数字变成 NestedInteger 对象,加入当前列表。
    • 最后返回栈顶的对象。

这种方法跟手动解析 JSON 或 XML 很像,工程里也常见。

示例测试及结果

我们写一个小 demo 来测试:

let solution = Solution()let ex1 = "324"
let result1 = solution.deserialize(ex1)
print("输入: \(ex1)")
print("输出: \(result1.toString())\n")let ex2 = "[123,[456,[789]]]"
let result2 = solution.deserialize(ex2)
print("输入: \(ex2)")
print("输出: \(result2.toString())\n")

运行结果:

输入: 324
输出: 324输入: [123,[456,[789]]]
输出: [123,[456,[789]]]

这跟题目要求完全一致。

时间复杂度

  • 我们只遍历了一次字符串,每个字符都处理一次,所以 O(n)
  • 数字解析和栈操作都是常量时间。

空间复杂度

  • 栈的深度最多等于嵌套层数。
  • 所以空间复杂度是 O(n),主要用于存储结果对象和栈。

总结

这道题看起来是算法题,其实就是一个小型的 语法解析器
它考察了两个核心点:

  1. 如何设计数据结构来表达嵌套关系。
  2. 如何用栈来解析字符串,避免递归层数过深。

在实际场景中,这个思路非常有用,比如:

  • 写一个轻量级的配置解析器(像 JSON、YAML)。
  • 解析游戏关卡脚本,描述嵌套的任务和事件。
  • 从日志中提取嵌套的数据结构,方便分析。

所以,这不仅仅是一道刷题,更是把我们带入了“编译原理”的世界。

http://www.dtcms.com/a/394908.html

相关文章:

  • windows系统使用sdkman管理java的jdk版本,WSL和Git Bash哪个更能方便管理jdk版本
  • 生产环境K8S的etcd备份脚本
  • Mac电脑多平台Git账号配置
  • Etcd详解:Kubernetes的大脑与记忆库
  • 深刻理解PyTorch中RNN(循环神经网络)的output和hn
  • 大模型如何赋能写作:从创作到 MCP 自动发布的全链路解析
  • C++设计模式之创建型模式:工厂方法模式(Factory Method)
  • 传输层协议——UDP/TCP
  • 三板汇茶咖空间签约“可信资产IPO与数链金融RWA”链改2.0项目联合实验室
  • 【MySQL】MySQL 表文件误删导致启动失败及无法外部连接解决方案
  • LVS简介
  • 如何将联系人从iPhone转移到iPhone的7种方法
  • 『 MySQL数据库 』MySQL复习(一)
  • 3005. 最大频率元素计数
  • ACP(七)优化RAG应用提升问答准确度
  • 鸿蒙:使用bindPopup实现气泡弹窗
  • Langchan4j 框架 AI 无限循环调用文件创建工具解决方案记录
  • Python GIS 开发里最核心的4个基础组件(理论+实操篇)
  • 关于跨域和解决方案
  • 学习日报 20250921|LoadingCache
  • 聚力赋能|竹云受邀出席2025华为全联接大会
  • 抓取 Dump 文件与 WinDbg 使用详解:定位 Windows 程序异常的利器
  • 计算机组成原理:指令周期
  • 老题新解|简单算术表达式求值
  • RustFS与其他新兴存储系统(如SeaweedFS)相比有哪些优势和劣势?
  • WPS标点符号换行问题解决
  • 开发团队的文档自动化革命:WPS+cpolar实战录
  • 【Linux】文本编辑器Vim
  • flink1.18下游配置多个sink
  • 如何删除 MySQL 数据库中的所有数据表 ?