LeetCode 228. 汇总区间
📌 题目描述
题目级别:简单
给定一个 无重复元素 的 有序 整数数组 nums 。
返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个区间但不属于 nums 的数字 x 。
列表中的每个区间范围 [a,b] 应该按如下格式输出:
-
"a->b",如果a != b -
"a",如果a == b -
示例 1:
输入:
nums = [0,1,2,4,5,7]输出:
["0->2","4->5","7"]
💡 破题思路:双游标区间扫描 (Interval Scanning)
既然数组是有序的,那么所有连续的数字必然是挨在一起的。我们可以用一个外层 while 循环来管理所有的区间:
- 锁定起点 :设当前区间的左端点下标为
start = i,对应的数值是nums[start]。 - 探路终点 :用游标
i向右不断试探,只要后面的数字和前面的数字相差正好为1(即连续递增),就让i继续往右走。 - 格式化组装 :
- 当探路停止时,当前的
i就是这个连续区间的右端点。 - 如果
start == i,说明区间只有一个数,直接转成字符串to_string(nums[start])。 - 如果
start != i,说明区间有多个数,组装成"a->b"的格式。
- 当探路停止时,当前的
- 推进外层循环 :将
i++,跨入下一个新区间继续扫描。
⚠️ 极客避坑点:
- 类型转换 :千万不能直接用
string(nums[i]),那是在构造特定长度的字符串。必须使用标准库的std::to_string()将整型安全转换为文本。 - 整型溢出防范 :在判断连续性时,如果数组中出现了
INT_MAX,直接相减可能会导致整型溢出。稳妥起见可以转换为long long再做差值比较。
💻 C++ 代码实现 (满分解法)
cpp
class Solution {
public:
vector<string> summaryRanges(vector<int>& nums) {
vector<string> res;
int n = nums.size();
int i = 0;
while (i < n)
{
int start = i; // 记录当前区间的起点
// 向右探路,只要连续递增就一直往前走
while (i + 1 < n && (long long)nums[i + 1] - nums[i] == 1)
{
i++;
}
// 此时 i 停在了当前区间的终点
string ss = to_string(nums[start]);
// 起点和终点不同,说明是多元素的区间,拼接 "->b"
if (start != i)
{
ss += "->" + to_string(nums[i]);
}
res.push_back(ss);
i++; // 步入下一个新区间
}
return res;
}
};