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

Swift 实战:从数据流到不重叠区间的高效转换

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

文章目录

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

摘要

在日常开发中,我们经常会遇到这样的需求:从一串不断到来的数据中,实时维护一组“合并好的区间”。比如,日志的连续时间段、用户连续签到天数、实时数据的连续区间等。
LeetCode 第 352 题 Data Stream as Disjoint Intervals 就是这种场景的典型抽象。它要求我们在数据流中动态添加数字,并随时返回当前数字集合的“不重叠有序区间”表示。

本文将用 Swift 从零实现一个高效的 SummaryRanges 类,逐步分析设计思路,并提供一个可直接运行的 Demo。

描述

题目要求我们实现这样一个类:

  1. SummaryRanges():初始化对象,数据流初始为空。
  2. addNum(val):添加一个数字到数据流中。
  3. getIntervals():返回当前数据流中所有数字的合并区间列表,且区间必须有序且不重叠。

例子

假设我们依次调用:

addNum(1) → getIntervals() → [[1, 1]]
addNum(3) → getIntervals() → [[1, 1], [3, 3]]
addNum(7) → getIntervals() → [[1, 1], [3, 3], [7, 7]]
addNum(2) → getIntervals() → [[1, 3], [7, 7]]
addNum(6) → getIntervals() → [[1, 3], [6, 7]]

你可以看到,数字进来后如果能与已有区间相连,就会被合并;否则,它会自己成为一个新区间。

题解答案

最直接的解法是:

  • 用一个 有序集合有序数组 存储所有出现过的数字;
  • 每次 getIntervals() 遍历这些数字,按连续性分组形成区间。

但是这样有两个问题:

  1. 每次获取区间都要 O(n) 遍历,调用频繁时性能差;
  2. 插入数字时需要保持有序,普通数组插入 O(n) 会慢。

更好的方法是:

  • 使用 有序字典(SortedDictionary)TreeMap 思路 存储每个区间;
  • addNum 时直接合并到现有区间,避免重复遍历;
  • 这样 getIntervals 可以直接 O(k) 返回区间列表(k 是区间数)。

Swift 没有内置 TreeMap,但可以用 SortedDictionary 的思路,或直接用普通字典 + 手动合并(配合有序 keys)。

题解代码分析

下面是 Swift 代码实现,并且是可运行的 Demo 模块。

import Foundationclass SummaryRanges {private var intervals: [(Int, Int)] = []init() {}func addNum(_ val: Int) {// 如果 intervals 为空,直接加if intervals.isEmpty {intervals.append((val, val))return}var newStart = valvar newEnd = valvar merged: [(Int, Int)] = []var inserted = falsefor (start, end) in intervals {if end + 1 < newStart {// 当前区间完全在新数左边merged.append((start, end))} else if newEnd + 1 < start {// 当前区间完全在新数右边if !inserted {merged.append((newStart, newEnd))inserted = true}merged.append((start, end))} else {// 有交集或相邻,合并区间newStart = min(newStart, start)newEnd = max(newEnd, end)}}if !inserted {merged.append((newStart, newEnd))}intervals = merged}func getIntervals() -> [[Int]] {return intervals.map { [$0.0, $0.1] }}
}// Demo
let summaryRanges = SummaryRanges()
summaryRanges.addNum(1)
print(summaryRanges.getIntervals()) // [[1, 1]]
summaryRanges.addNum(3)
print(summaryRanges.getIntervals()) // [[1, 1], [3, 3]]
summaryRanges.addNum(7)
print(summaryRanges.getIntervals()) // [[1, 1], [3, 3], [7, 7]]
summaryRanges.addNum(2)
print(summaryRanges.getIntervals()) // [[1, 3], [7, 7]]
summaryRanges.addNum(6)
print(summaryRanges.getIntervals()) // [[1, 3], [6, 7]]

代码解析

  1. 数据结构选择
    用一个有序的 [(start, end)] 元组数组 intervals 存储区间,每次插入新数字时,按顺序扫描并决定合并还是插入。

  2. 插入逻辑

    • 如果新区间完全在某个区间左侧并且不相连,直接放进合并结果;
    • 如果完全在右侧并且不相连,先放入新数字区间再放现有区间;
    • 如果有交集或相邻,更新 newStartnewEnd 进行合并。
  3. 返回结果
    getIntervals() 直接 O(k) 遍历区间数组并转成二维数组返回。

示例测试及结果

运行上面的 Demo,会输出:

[[1, 1]]
[[1, 1], [3, 3]]
[[1, 1], [3, 3], [7, 7]]
[[1, 3], [7, 7]]
[[1, 3], [6, 7]]

这与题目中的预期完全一致。

时间复杂度

  • addNum:O(k),k 为区间数(最坏情况下 k≈n,但通常 k << n);
  • getIntervals:O(k);
  • 对于数据流比较稀疏的情况,性能非常好。

空间复杂度

  • 额外存储 intervals 数组,最多存储 n 个不相交区间,空间复杂度 O(n)。

总结

这道题虽然名字看起来很抽象,但在很多实际场景里都有用武之地,比如:

  • 实时统计用户的连续签到区间;
  • 日志中连续时间片段的合并;
  • 实时视频或音频帧缺失检测。

用 Swift 实现时,我们不需要复杂的平衡树结构,也能通过有序数组+一次扫描的方式做到高效插入和查询。在数据流中区间合并的问题,关键是保持区间有序性和及时合并,这样才能保证后续查询快速、结构清晰。

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

相关文章:

  • 《书写范式》——代码如诗,诗娟代码(Python)(附精巧“九九表”生成代码)
  • 《Linux基础知识-2》
  • 【2025】Datawhale AI夏令营-多模态RAG-Task3笔记-解决方案进阶
  • HGDB的分区表实现SQL Server的分区视图
  • 邀您参与 “直通乌镇” Spring AI Alibaba 开源竞技挑战赛!
  • 2025 最应避免的摄影陷阱以及解决方案
  • 八月补丁星期二:微软修复 111 个漏洞
  • String里常用的方法
  • Vue项目生产环境性能优化实战指南
  • 服务器查看 GPU 占用情况的方法
  • mac环境下安装git并配置密钥等
  • 搜索引擎核心机制解析
  • RabbitMQ面试精讲 Day 21:Spring AMQP核心组件详解
  • 详解Windows(二十)——恶意软件清除
  • CV 医学影像分类、分割、目标检测,之【腹腔多器官语义分割】项目拆解
  • 1.4.2 嵌入(embedding)模式:让人工智能大模型为你的产品或业务助力
  • 大模型微调【1】之入门
  • 实践基地授牌:重庆五一职院与成都影像产业园强实训
  • Coze Studio 概览(十)--文档处理详细分析
  • CW32L011电机开发板控制教程
  • C++ 面向对象四大特性:面试深度解析
  • 一个接口多个实现类,如何动态调用
  • 神经网络的核心组件解析:从理论到实践
  • ARM 实操 流水灯 按键控制 day53
  • Django REST Framework视图
  • HarmonyOS NDK的JavaScript/TypeScript与C++交互机制
  • Flask vs Django:微框架与一站式对决
  • web安全开发,在线%射击比赛管理%系统开发demo,基于html,css,jquery,python,django,三层mysql数据库
  • C# 异常处理与拦截全攻略:try/catch/finally、using、ASP.NET Core 中间件与过滤器一网打尽(含完整示例)
  • tRAP(tRNA 活性预测器)