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

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

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


相关推荐
用户9704438781168 分钟前
taobao商品详情数据获取实战方法
算法·html
yu20241128 分钟前
【【异世界历险之数据结构世界(二叉树)】】
数据结构·算法
补三补四1 小时前
RNN(循环神经网络)
人工智能·rnn·深度学习·神经网络·算法
逐闲3 小时前
LeetCode热题100【第一天】
算法·leetcode
爱吃涮毛肚的肥肥(暂时吃不了版)3 小时前
剑指offer——模拟:顺时针打印矩阵
算法·leetcode·矩阵
chao_7893 小时前
动态规划题解——乘积最大子数组【LeetCode】
python·算法·leetcode·动态规划
今天背单词了吗9804 小时前
算法学习笔记:16.哈希算法 ——从原理到实战,涵盖 LeetCode 与考研 408 例题
笔记·学习·算法
前端拿破轮4 小时前
字符串消消乐你会吗?😋😋😋
算法·leetcode·面试
EndingCoder4 小时前
图算法在前端的复杂交互
前端·算法·图算法
kanhaoning5 小时前
将重排序大模型Qwen3-Reranker-8B的知识蒸馏到小模型BGE-reranker-v2-m3上
算法