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

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

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


相关推荐
放荡不羁的野指针6 小时前
leetcode150题-双指针
数据结构·算法·leetcode
好学且牛逼的马6 小时前
【Hot100|15-LeetCode 238. 除自身以外数组的乘积】
数据结构·算法·leetcode
Tisfy6 小时前
LeetCode 3651.带传送的最小路径成本:动态规划
算法·leetcode·动态规划·题解·排序
努力学习的小廉6 小时前
我爱学算法之—— 递归回溯综合(一)
算法·深度优先
m0_736919106 小时前
C++中的策略模式实战
开发语言·c++·算法
孞㐑¥6 小时前
算法—位运算
c++·经验分享·笔记·算法
软件算法开发6 小时前
基于卷尾猴优化的LSTM深度学习网络模型(CSA-LSTM)的一维时间序列预测算法matlab仿真
深度学习·算法·matlab·lstm·一维时间序列预测·卷尾猴优化·csa-lstm
高洁016 小时前
知识图谱如何在制造业实际落地应用
深度学习·算法·机器学习·数据挖掘·知识图谱
BHXDML6 小时前
数据结构:(二)逻辑之门——栈与队列
java·数据结构·算法
晚风吹长发7 小时前
初步了解Linux中的信号捕捉
linux·运维·服务器·c++·算法·进程·x信号