题目描述和要求
给定一个无重复元素的有序整数数组 nums,要求返回恰好覆盖数组中所有数字的最小有序区间范围列表。即,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字。
列表中的每个区间范围 [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”
解题思路
一种简单的方法是遍历数组,对连续的数字进行合并形成区间。具体步骤如下:
- 初始化一个结果列表,用于存储最终的区间范围。
- 使用双指针,分别标记区间的起始和结束位置。
- 遍历数组,如果当前数字与前一个数字连续,则更新结束位置;否则,将前一个区间加入结果列表,并更新起始和结束位置。
- 将最后一个区间加入结果列表。
- 返回结果列表。
算法实现
import java.util.ArrayList; import java.util.List; public class SummaryRanges { public List<String> summaryRanges(int[] nums) { List<String> result = new ArrayList<>(); if (nums == null || nums.length == 0) { return result; } int start = nums[0]; int end = nums[0]; for (int i = 1; i < nums.length; i++) { if (nums[i] == end + 1) { end = nums[i]; } else { if (start == end) { result.add(Integer.toString(start)); } else { result.add(start + "->" + end); } start = nums[i]; end = nums[i]; } } if (start == end) { result.add(Integer.toString(start)); } else { result.add(start + "->" + end); } return result; } }
复杂度分析
- 时间复杂度:O(n),其中 n 为数组的长度。遍历一次数组。
- 空间复杂度:O(1)。除了结果列表外,不需要额外的空间。
测试和验证
编写测试用例对算法进行验证,确保其正确性和健壮性。
public class Main { public static void main(String[] args) { SummaryRanges summaryRanges = new SummaryRanges(); int[] nums1 = {0, 1, 2, 4, 5, 7}; System.out.println(summaryRanges.summaryRanges(nums1)); // ["0->2", "4->5", "7"] int[] nums2 = {0, 2, 3, 4, 6, 8, 9}; System.out.println(summaryRanges.summaryRanges(nums2)); // ["0", "2->4", "6", "8->9"] } }
总结和拓展
本题通过简单的数组遍历和区间合并的方式,实现了求解给定有序整数数组的最小区间范围列表。这个算法简单高效,在处理类似问题时是一个不错的选择。
此外,我们也可以考虑优化算法以提高效率,例如使用更高效的数据结构或算法来实现同样的功能。
参考资料
- 《力扣经典150题》
- LeetCode 官方网站