题目描述#

给定一个无重复元素的有序整数数组 nums,需要返回恰好覆盖数组全部数字的最小有序区间范围列表。

如果某个区间只有一个数字,就输出 "a";如果某个区间从 a 连续到 b,就输出 "a->b"

知识边界#

分组循环#

这题适合用分组循环来做。因为数组已经有序,而且没有重复元素,所以只要相邻两个数满足 nums[j+1] == nums[j] + 1,它们就属于同一组。

遍历时先固定一组的起点 i,再让 j 一直向右扩展,找到这一组的结尾。这样 [i, j] 就对应一个完整的连续区间。

如果 i == j,说明这一组只有一个数字,直接转成字符串加入答案;如果 i != j,说明这一组是一段连续区间,就按 "左端点->右端点" 的格式加入答案。处理完这一组后,把 i 跳到 j + 1,继续找下一组。

这种写法的核心就是:不要一边扫描一边零散处理,而是先把满足同一性质的一整段找完整,再统一处理这一段。这里这一段的性质,就是“相邻元素连续加一”。

思路#

因为 nums 本身已经升序排列,所以每个区间一定对应数组中的一段连续下标。我们从左到右扫描数组,每次找到当前连续段的右边界,再根据这一段长度决定输出单个数字还是区间字符串。

整个过程中,每个元素最多进入一次某个分组,时间复杂度是 O(n)。除结果数组外,只用了少量指针变量,因此额外空间复杂度是 O(1)。如果输入是空数组,循环不会进入,最终直接返回空结果。

代码#

import "strconv"

func summaryRanges(nums []int) []string {
	ans := []string{}
	n := len(nums)
	for i := 0; i < n; {
		j := i
		// 找这一组的结尾
		for j < n-1 && nums[j+1] == nums[j]+1 {
			j++
		}
		// 处理这一组 [i, j]
		if i == j {
			ans = append(ans, strconv.Itoa(nums[i]))
		} else {
			ans = append(ans, strconv.Itoa(nums[i])+"->"+strconv.Itoa(nums[j]))
		}
		// 进入下一组
		i = j + 1
	}
	return ans
}
本站总访问量  ·  访客数
你的IP 获取中…