一、题目描述
给定一个 无重复元素 的 有序 整数数组 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"] 解释:区间范围是: [0,2] --> "0->2" [4,5] --> "4->5" [7,7] --> "7"
示例 2:
输入:nums = [0,2,3,4,6,8,9] 输出:["0","2->4","6","8->9"] 解释:区间范围是: [0,0] --> "0" [2,4] --> "2->4" [6,6] --> "6" [8,9] --> "8->9"
提示:
0 <= nums.length <= 20
-2^31 <= nums[i] <= 2^31 - 1
nums
中的所有值都 互不相同nums
按升序排列
二、解题思路
- 初始化一个空的列表
result
用于存放结果区间。 - 遍历数组
nums
,使用两个变量start
和end
分别记录区间的起始和结束位置。 - 对于数组中的每个元素,检查它与前一个元素的关系:
- 如果当前元素与前一个元素的差值大于1,说明当前元素不与前一个元素在同一个区间内。此时,将
[start, end]
区间加入result
列表,并更新start
为当前元素的位置。 - 如果当前元素与前一个元素的差值为1,则更新
end
为当前元素的位置。
- 如果当前元素与前一个元素的差值大于1,说明当前元素不与前一个元素在同一个区间内。此时,将
- 在遍历结束后,不要忘记将最后一个区间
[start, end]
加入result
列表。 - 根据区间的起始和结束位置,构建相应的字符串表示,如果
start == end
则只添加start
,否则添加"start->end"
。
三、具体代码
import java.util.ArrayList;
import java.util.List;
class Solution {
public List<String> summaryRanges(int[] nums) {
List<String> result = new ArrayList<>();
int i = 0;
while (i < nums.length) {
int start = nums[i];
// 移动到当前区间的末尾
while (i + 1 < nums.length && nums[i + 1] == nums[i] + 1) {
i++;
}
// 当前区间的结束位置
int end = nums[i];
// 构建区间字符串
if (start == end) {
result.add(Integer.toString(start));
} else {
result.add(start + "->" + end);
}
// 移动到下一个区间的起始位置
i++;
}
return result;
}
}
这段代码通过一个循环遍历整个数组,并且在循环内部使用一个内层循环来找到每个连续区间的末尾。当找到一个非连续的元素时,就会构建区间字符串并将其添加到结果列表中。最后返回这个列表作为函数的输出。
四、时间复杂度和空间复杂度
1. 时间复杂度
- 遍历数组
nums
的时间复杂度为 O(n),其中 n 是数组nums
的长度。 - 在遍历过程中,内层
while
循环用于找到连续区间的末尾。对于数组中的每个元素,最多只会被访问一次,因此内层循环的时间复杂度也是 O(n)。 - 综上所述,总的时间复杂度是 O(n) + O(n) = O(n),即线性的时间复杂度。
2. 空间复杂度
result
是一个列表,用于存储区间字符串。在最坏的情况下,如果数组nums
中的所有元素都不连续,则result
的大小将与nums
相同,即 O(n)。- 除此之外,代码中只使用了常数个额外空间(变量
start
,end
和循环索引i
),这些不依赖于输入数组的大小,因此空间复杂度为 O(1)。 - 综合考虑,总的空间复杂度是 O(n) + O(1) = O(n),即线性的空间复杂度。
这里,n 表示数组 nums
的长度。代码的时间复杂度是线性的,因为它只需要遍历数组一次。空间复杂度也是线性的,因为它需要存储与输入数组大小成比例的输出结果。
五、总结知识点
-
类定义:
class
关键字用于定义一个类。- 类名通常以大写字母开头,遵循驼峰命名法(CamelCase)。
-
方法定义:
- 方法定义在类内部,包括访问修饰符(
public
)、返回类型(List<String>
)、方法名(summaryRanges
)以及参数列表(int[] nums
)。
- 方法定义在类内部,包括访问修饰符(
-
数据结构:
List<String>
是一个接口,表示一个元素类型为String
的列表。ArrayList
是List
接口的一个实现,提供了可调整大小的数组功能。
-
初始化:
- 使用
new
关键字来创建ArrayList
的实例。
- 使用
-
循环结构:
while
循环用于重复执行一段代码,直到给定的条件不再满足。
-
数组操作:
- 通过索引访问数组元素(
nums[i]
)。 - 数组的长度通过
.length
属性获取。
- 通过索引访问数组元素(
-
条件语句:
if-else
语句用于基于条件执行不同的代码块。
-
字符串操作:
- 使用
Integer.toString()
方法将整数转换为字符串。 - 使用
+
运算符进行字符串连接。
- 使用
-
方法调用:
- 调用
ArrayList
的add()
方法将元素添加到列表中。
- 调用
-
返回值:
- 使用
return
关键字返回方法的结果。
- 使用
-
变量声明和赋值:
- 声明变量(如
int i = 0;
)并为其赋初值。
- 声明变量(如
-
逻辑运算符:
- 使用
&&
表示逻辑与运算。 - 使用
==
和!=
进行比较运算。
- 使用
-
自增运算符:
- 使用
++
操作符来递增变量的值。
- 使用
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。