小哆啦解题记 · 数字连续段谜案

📘 题号:228. 汇总区间 - 力扣(LeetCode)

🧪 目标:把一个有序数组拆解成多个最小连续区间段

🛠️ 技术关键词:双指针、去重、边界判断、字符串拼接、时间复杂度分析


第一章:失踪的数字碎片

大雄一脸疑惑地看着一份看似完整的数字清单 [0, 1, 2, 4, 5, 7],问哆啦A梦:

"能不能把它整理成'连续段'?我不想一个一个读!"

哆啦A梦掏出铜锣烧,咀嚼着说:

"你想要的结果是 ['0->2', '4->5', '7'],对吧?"


第二章:初级代码的翻车现场

大雄兴冲冲写下第一版代码:

ini 复制代码
function summaryRanges(nums: number[]): string[] {
    let show = 0
    let count = 0
    let sArr: string[] = []
    for (let fast = 1; fast <= nums.length; fast++) {
        if (nums[show + count] + 1 == nums[fast]) {
            count++
        } else {
            if (count == 0) {
                sArr.push(`${nums[show]}`)
                show += 1
            } else {
                sArr.push(`${nums[show]}->${nums[show + count]}`)
                show += count + 1
                count = 0
            }
        }
    }
    return sArr
}

问题出现了:

  • 😵 如果有重复元素,[1,1,2] 就直接脑震荡
  • 😵 访问 nums[fast] 时,fast == nums.length 会越界
  • 😵 "last + 1 == nums[fast]" 判断不严谨:连续值判断并不意味着"index连续 + 值连续"
  • 😵 逻辑太绕,show + count 维护困难

第三章:Bug排查 + 优化决策

为什么会出错?

因为你假设了值是连续的,索引也是连续的。但如果数组里有重复或者空洞,比如 [1,1,2,3,7],你就会判断错。

怎么修?

✅ 方法一:先去重

Set 去掉重复值,确保连续性判断不被干扰

✅ 方法二:优化指针与条件

放弃 count,用 start 记录区间起点,i 遍历时动态判断是否到了"连续段的终点"


第四章:优化代码登场(可读性 + 正确性)

typescript 复制代码
function summaryRanges(nums: number[]): string[] {
    if (nums.length === 0) return []

    const result: string[] = []
    const uniqueNums = Array.from(new Set(nums)) // 去重避免重复数字干扰

    let start = uniqueNums[0]

    for (let i = 1; i <= uniqueNums.length; i++) {
        // 到数组尾部 or 当前不连续
        if (i === uniqueNums.length || uniqueNums[i] !== uniqueNums[i - 1] + 1) {
            if (start === uniqueNums[i - 1]) {
                result.push(`${start}`)
            } else {
                result.push(`${start}->${uniqueNums[i - 1]}`)
            }
            // 更新 start 为下一个段的起点
            start = uniqueNums[i]
        }
    }

    return result
}

第五章:为什么要去重?

这点很容易被忽视,但重复数字会让我们误判连续段的"断裂"。

css 复制代码
例子:nums = [1,1,2,3]
去重后:nums = [1,2,3]
连续段 = ['1->3']
不去重时:1 和 1 会被误判为"断裂" -> ['1', '1->3']

第六章:真的 O(n) 吗?

你可能注意到了:

我们用到了 .sort() 吗?没有!

那为啥还能保证区间是"有序"的?因为题目中已明确:输入数组是有序的!

所以我们只做了一次 O(n) 遍历,并用常数空间(Set 和 result)

最终时间复杂度:

  • 去重 + 遍历:O(n)
  • 空间复杂度:O(n) (输出区间)

第七章:小哆啦的记忆卡

技术点 含义
Set 去重 保证连续判断的准确性
双指针(start + i) 跟踪区间头尾
i ≤ len 遍历 + 提前判断断裂 确保每一段被完整结算
输出 a 或 a->b 取决于当前段长度

🧾 技术启示录

  • ✅ 遇到区间合并问题,第一时间想"是否连续 + 是否有重复"
  • ✅ 写循环时注意遍历尾部是否要提前触发逻辑
  • ✅ 条件逻辑简化结构,减少变量依赖,更可维护
  • ✅ 函数要能解释每个逻辑分支"为何而写"

🧨 窗外彩蛋:

胖虎看着自己的 [1,2,2,3,5,6],抱怨道:

"怎么我得到的是 ["1->3","5->6"],不是 ["1->2","2->3","5->6"]?"

哆啦A梦一脸无奈:

"你不去重,就像连续剧中插播广告,剧情不顺你能怪我?"


相关推荐
智者知已应修善业1 小时前
【51单片机8位数码管同时倒计时从9999】2024-1-25
c++·经验分享·笔记·算法·51单片机
洛水水1 小时前
【力扣100题】86.柱状图中最大的矩形
算法·leetcode·职场和发展
渡之1 小时前
GRiM-Net 深度解析 | 无人机 GNSS 拒止场景下两阶段跨视角视觉定位框架
深度学习·算法·动态规划·无人机
测试仪器廖生135902563851 小时前
罗德与施瓦茨 FSP13频谱分析仪FSP30
网络·人工智能·算法
happymaker06261 小时前
LeetCodeHot100——560.和为K的子数组
算法
dtq04242 小时前
C语言刷题数组5,6(求平均值,求最大值)
c语言·数据结构·算法
郭梧悠2 小时前
Hash算法入门Hash冲突解决方案
算法·哈希算法
洛水水2 小时前
【力扣100题】81.寻找两个正序数组的中位数
数据结构·算法·leetcode
happymaker06263 小时前
LeetCodeHot100——155.最小栈
算法
洛水水3 小时前
【力扣100题】85.每日温度
算法·leetcode·职场和发展