问题描述
小明正在设计一台打点计数器,该计数器可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。小明需要你帮助他计算,在给定的多组数字范围内,计数器会打多少个点。
例如,给定三个数字范围 [1, 4], [7, 10], 和 [3, 5],计数器首先将这些范围合并,变成 [1, 5] 和 [7, 10],然后计算这两个范围内共有多少个唯一数字,即从 1 到 5 有 5 个数字,从 7 到 10 有 4 个数字,共打 9 个点。
测试样例
样例1:
输入:
inputArray = [[1, 4], [7, 10], [3, 5]]
输出:9
样例2:
输入:
inputArray = [[1, 2], [6, 10], [11, 15]]
输出:12
样例3:
输入:
inputArray = [[1, 3], [2, 6], [8, 10]]
输出:9
题目分析
- 合并重叠范围:首先,我们需要将所有重叠的范围合并成一个连续的范围。这可以通过对输入的范围进行排序,然后逐个检查并合并重叠的范围来完成。
- 计算唯一数字的数量:一旦我们有了合并后的范围,我们就可以计算每个范围内有多少个唯一数字。这可以通过计算每个范围的上限和下限之间的差值加一来完成。
代码实现
import java.util.Arrays;
public class Main {
public static int solution(int[][] ranges) {
if (ranges.length == 0) {
return 0;
}
// 按区间的起始点排序
Arrays.sort(ranges, (a, b) -> Integer.compare(a[0], b[0]));
int totalPoints = 0;
int start = ranges[0][0];
int end = ranges[0][1];
for (int i = 1; i < ranges.length; i++) {
int[] currentRange = ranges[i];
// 如果当前区间与之前的区间有重叠或相邻,则合并区间
if (currentRange[0] <= end + 1) {
end = Math.max(end, currentRange[1]); // 更新结束点
} else {
// 计算非重叠区间的长度
totalPoints += (end - start + 1); // 添加当前区间的长度
// 更新新的区间
start = currentRange[0];
end = currentRange[1];
}
}
// 加上最后一个合并后的区间
totalPoints += (end - start + 1);
return totalPoints;
}
public static void main(String[] args) {
// You can add more test cases here
int[][] testArray1 = {{1, 4}, {7, 10}, {3, 5}};
int[][] testArray2 = {{1, 2}, {6, 10}, {11, 15}};
System.out.println(solution(testArray1) == 9);
System.out.println(solution(testArray2) == 12);
}
}
代码逻辑分析
-
初始化计数器和范围:初始化
totalPoints变量为 0,用于存储最终的唯一数字总数。同时,初始化start和end变量为第一个范围的起始点和结束点。 -
遍历范围:从第二个范围开始遍历排序后的范围数组。对于每个当前范围
currentRange:- 如果
currentRange的起始点小于或等于end + 1,则表示当前范围与前一个范围重叠或相邻。在这种情况下,通过取end和currentRange的结束点的最大值来更新end。 - 如果
currentRange的起始点大于end + 1,则表示当前范围与前一个范围不重叠。在这种情况下,计算前一个范围的长度(end - start + 1)并将其添加到totalPoints中。然后,更新start和end为当前范围的起始点和结束点。
- 如果
-
计算最后一个范围的长度:在循环结束后,计算最后一个合并后的范围的长度(
end - start + 1)并将其添加到totalPoints中。
时间复杂度分析
-
合并操作:
- 在 for 循环中,对于每个范围,代码执行的操作(比较和可能的赋值)都是常数时间操作,即 O(1)。因此,合并操作的总时间复杂度为 O(n)。
-
排序操作:
Arrays.sort方法对范围数组进行排序,其时间复杂度为 O(n log n),其中 n 是范围数组的长度。这是因为 Java 中的Arrays.sort方法通常使用 Timsort 算法,它在最佳和平均情况下的时间复杂度为 O(n log n)。
总结
使用豆包MarsCode AI工具后,我的解题速度得到了显著提升,同时在知识整理和错题分析方面也有了长足的进步。我计划继续利用AI的功能结合传统学习资源,来加强我的算法基础,并挑战更高难度的题目。
希望我的这些经验能够对其他初学者有所启发和帮助。让我们共同享受学习算法带来的乐趣,并在这个过程中不断进步和成长!