LeetCode 228. 汇总区间:解题思路+代码详解

LeetCode简单难度的经典区间题------228. 汇总区间,这道题是区间处理的入门必刷款,核心考察「双指针遍历」和「边界场景处理」,代码不长但细节拉满,新手也能快速上手,话不多说,直接开干!

一、题目解读(原题复刻+重点提炼)

先看原题要求,帮大家提炼关键信息,避免踩坑:

✨ 关键提醒(题目隐含条件,决定解题方向)

  • 数组是「有序」的:无需额外排序,直接遍历即可判断连续区间;

  • 无重复元素:不用考虑去重,只需关注"当前元素与前一个元素是否连续";

  • 最小有序区间:每个区间必须是"连续递增1"的,不能跳过元素,也不能包含数组中没有的数字。

举个直观例子,帮大家理解需求:

  • 输入 nums = [0,1,2,4,5,7] → 输出 ["0->2","4->5","7"]

  • 输入 nums = [1] → 输出 ["1"]

  • 输入 nums = [] → 输出 [](边界场景,容易忽略)

二、解题思路(核心:双指针划定连续区间)

这道题的核心逻辑很简单:用两个指针(start 和 end),动态标记当前连续区间的「起始下标」和「结束下标」,遍历数组时判断区间是否断开,断开则格式化当前区间,再重置指针,继续寻找下一个连续区间。

具体步骤拆解(图文结合更易理解,新手可跟着走):

  1. 初始化:定义结果数组 res(存储最终格式化的区间字符串),定义 start 和 end 指针,初始都指向数组第0个元素(即 start = end = 0),表示初始区间从第一个元素开始。

  2. 遍历数组:从第二个元素(i=1)开始遍历,因为要和前一个元素(i-1)比较,判断是否连续。

  3. 判断区间是否断开:若当前元素 nums[i] 与前一个元素 nums[i-1] 的差值 > 1,说明当前区间断开(前一个区间结束,新的区间开始)。

  4. 格式化当前区间:若 start == end(说明当前区间只有一个元素),直接将该元素转为字符串存入 res;若不相等,格式化为 "start->end" 存入 res。

  5. 重置指针:将 start 和 end 都指向当前下标 i,开始标记新的连续区间。

  6. 区间未断开:若差值 ≤ 1(题目中无重复元素,差值只能是1),说明当前元素仍在连续区间内,只需将 end 指针更新为 i,扩大当前区间。

  7. 处理最后一个区间:遍历结束后,最后一个区间还未存入 res(因为循环中只处理"断开时"的区间),需单独格式化并存入 res。

  8. 返回结果:返回 res 数组。

💡 小技巧:之所以用下标指针(而非直接存数值),是因为数组有序无重复,通过下标访问数值更灵活,也能避免额外存储数值的空间消耗。

三、完整代码+逐行拆解

先贴出可直接提交的完整代码(TypeScript 版本,JavaScript 可直接删除类型注解使用),再逐行拆解关键细节,新手也能看懂每一步的作用:

typescript 复制代码
function summaryRanges(nums: number[]): string[] {
  const res: string[] = [];
  // 边界处理:空数组直接返回空结果(容易忽略的坑)
  if (nums.length === 0) return res;

  let start = 0;
  let end = 0;
  for (let i = 1; i < nums.length; i++) {
    // 核心判断:当前元素与前一个元素差值>1 → 区间断开
    if (nums[i] - nums[i - 1] > 1) {
      // 格式化当前区间,存入结果
      if (start === end) {
        res.push(nums[start].toString());
      } else {
        res.push(`${nums[start]}->${nums[end]}`);
      }
      // 重置指针,开始新的区间
      start = i;
      end = i;
    } else {
      // 区间未断开,扩大当前区间的结束位置
      end = i;
    }
  }
  // 处理最后一个区间(循环结束后未处理)
  if (start === end) {
    res.push(nums[start].toString());
  } else {
    res.push(`${nums[start]}->${nums[end]}`);
  }
  return res;
};

逐行拆解(重点标注易踩坑点)

  1. const res: string[] = [];:初始化结果数组,用于存储最终格式化的区间字符串(类型注解可省略,不影响运行)。

  2. if (nums.length === 0) return res;边界处理重点!若输入为空数组,直接返回空结果,避免后续访问 nums[start] 出现 undefined 错误(很多新手会忽略这个场景,导致提交失败)。

  3. let start = 0; let end = 0;:定义双指针,初始都指向数组第一个元素(下标0),标记当前连续区间的起始和结束位置。

  4. for (let i = 1; i < nums.length; i++):从第二个元素(下标1)开始遍历,因为要和前一个元素(i-1)比较,判断是否连续。

  5. if (nums[i] - nums[i - 1] > 1):核心判断条件------当前元素与前一个元素的差值大于1,说明两个元素不连续,前一个区间结束,需要格式化并存储。

  6. 内部判断 if (start === end) { ... } else { ... }:根据指针是否相等,判断当前区间是"单个元素"还是"连续区间",并按题目要求格式化存入 res。

  7. start = i; end = i;:区间断开后,重置双指针,指向当前元素(i),开始标记新的连续区间。

  8. else { end = i; }:若区间未断开(差值为1),只需更新 end 指针,将当前元素纳入当前连续区间,start 指针保持不变。

  9. 循环外部的 if...else...第二个易踩坑点!循环结束后,最后一个连续区间还未存入 res(因为只有"区间断开"时才会存入),所以需要单独处理,逻辑和循环内部的格式化逻辑一致。

  10. return res;:返回最终的区间字符串数组,完成解题。

四、测试用例(覆盖所有场景,提交前必测)

提交代码前,建议测试以下4个核心场景,确保代码无bug(覆盖普通场景、边界场景、特殊场景):

输入数组 nums 预期输出 场景说明
[0,1,2,4,5,7] ["0->2","4->5","7"] 普通场景:多连续区间+单个元素
[] [] 边界场景:空数组
[1] ["1"] 边界场景:单元素数组
[-1,0,2,3,4] ["-1->0","2->4"] 特殊场景:包含负数+连续区间

五、代码优化思路(可选,提升可读性)

上面的代码逻辑正确、可直接提交,但有一个小问题:「区间格式化」的逻辑重复了两次(循环内部和循环外部)。我们可以将格式化逻辑抽离成一个单独的函数,让代码更简洁、易维护。

优化后代码:

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

  let start = 0;
  let end = 0;
  for (let i = 1; i < nums.length; i++) {
    if (nums[i] - nums[i - 1] > 1) {
      // 调用格式化函数,减少重复代码
      res.push(formatRange(nums[start], nums[end]));
      start = i;
      end = i;
    } else {
      end = i;
    }
  }
  // 最后一个区间也调用格式化函数
  res.push(formatRange(nums[start], nums[end]));
  return res;
}

// 抽离区间格式化逻辑,单独封装
function formatRange(startNum: number, endNum: number): string {
  return startNum === endNum ? startNum.toString() : `${startNum}->${endNum}`;
}

优化点说明:

  • 新增 formatRange 函数,专门处理区间格式化,输入起始值和结束值,返回符合题目要求的字符串;

  • 主函数中两次格式化操作,均改为调用该函数,减少代码冗余,后续若需修改格式化规则(如修改连接符),只需修改一个地方即可。

六、解题总结(核心考点+新手提醒)

这道题虽然是简单题,但覆盖了算法入门的核心考点,也是面试中常考的"送分题",总结几点关键收获:

  1. 核心考点:双指针遍历 (动态划定区间)、边界场景处理 (空数组、单元素数组)、字符串格式化

  2. 新手避坑:一定要处理空数组场景,否则会出现 undefined 错误;循环结束后,别忘了处理最后一个区间;

  3. 延伸思考:这道题是「区间处理」的入门题,后续的区间合并、区间插入等中等难度题目,核心逻辑也离不开"双指针划定区间",掌握这道题的思路,能为后续刷题打下基础。

相关推荐
AIpanda88815 小时前
如何借助AI销冠系统提升数字员工在销售中的成效?
算法
啊阿狸不会拉杆15 小时前
《机器学习导论》第 7 章-聚类
数据结构·人工智能·python·算法·机器学习·数据挖掘·聚类
木非哲15 小时前
机器学习--从“三个臭皮匠”到 XGBoost:揭秘 Boosting 算法的“填坑”艺术
算法·机器学习·boosting
爱问问题的小李15 小时前
ue 动态 Key 导致组件无限重置与 API 重复提交
前端·javascript·vue.js
小辉同志15 小时前
437. 路径总和 III
算法·深度优先·广度优先
子兮曰15 小时前
深入Vue 3响应式系统:为什么嵌套对象修改后界面不更新?
前端·javascript·vue.js
笨笨阿库娅15 小时前
从零开始的算法基础学习
学习·算法
CHU72903515 小时前
直播商城APP前端功能全景解析:打造沉浸式互动购物新体验
java·前端·小程序
枫叶丹415 小时前
【Qt开发】Qt界面优化(一)-> Qt样式表(QSS) 背景介绍
开发语言·前端·qt·系统架构