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

📘 题号: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梦一脸无奈:

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


相关推荐
LeaderSheepH1 小时前
常见的排序算法
数据结构·算法·排序算法
周杰伦_Jay2 小时前
【图文详解】强化学习核心框架、数学基础、分类、应用场景
人工智能·科技·算法·机器学习·计算机视觉·分类·数据挖掘
violet-lz2 小时前
Linux静态库与共享库(动态库)全面详解:从创建到应用
算法
贝塔实验室2 小时前
ADMM 算法的基本概念
算法·数学建模·设计模式·矩阵·动态规划·软件构建·傅立叶分析
235163 小时前
【LeetCode】3. 无重复字符的最长子串
java·后端·算法·leetcode·职场和发展
微笑尅乐3 小时前
神奇的位运算——力扣136.只出现一次的数字
java·算法·leetcode·职场和发展
吃着火锅x唱着歌4 小时前
LeetCode 3105.最长的严格递增或递减子数组
算法·leetcode·职场和发展
小卡皮巴拉4 小时前
【笔试强训】Day1
开发语言·数据结构·c++·算法
初圣魔门首席弟子4 小时前
switch缺少break出现bug
c++·算法·bug
山烛4 小时前
OpenCV:人脸识别实战,3 种算法(LBPH/EigenFaces/FisherFaces)代码详解
opencv·算法·计算机视觉·人脸识别·lbph·eigenfaces·fisherfaces