问题描述
小明正在设计一台打点计数器,该计数器可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。小明需要你帮助他计算,在给定的多组数字范围内,计数器会打多少个点。
例如,给定三个数字范围 [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
算法设计
- 输入检查:
-
- 如果
inputArray为null或长度小于 1,返回 0。
- 如果
- 特殊情况处理:
-
- 如果
inputArray只有一个区间,直接返回该区间的长度。
- 如果
- 排序:
-
- 按区间的起始位置对
inputArray进行排序。
- 按区间的起始位置对
- 合并区间:
-
- 初始化结果
res为第一个区间的长度。 - 初始化
maxt为第一个区间的结束位置。 - 遍历排序后的区间,根据当前区间的起始位置和
maxt的关系,更新res和maxt。
- 初始化结果
复杂度分析
时间复杂度分析
- 输入检查:
- 这一步的时间复杂度是 O(1)。
- 特殊情况处理:
- 这一步的时间复杂度是 O(1)。
- 排序:
- 使用
Arrays.sort对inputArray进行排序。对于n个区间的排序,时间复杂度是 O(nlogn)。
- 初始化结果和最大结束位置:
- 这一步的时间复杂度是 O(1)。
- 遍历排序后的区间:
- 遍历
n个区间,时间复杂度是 O(n)。 - 在遍历过程中,每个区间的操作(如比较、更新
res和maxt)都是 O(1) 的操作。
综上所述,总的时间复杂度为: O(1)+O(1)+O(nlogn)+O(1)+O(n)=O(nlogn)
空间复杂度分析
- 输入检查:
- 这一步的空间复杂度是 O(1)。
- 特殊情况处理:
- 这一步的空间复杂度是 O(1)。
- 排序:
Arrays.sort的空间复杂度是 O(logn)(因为排序算法通常使用递归,递归栈的深度为 O(logn)。
- 初始化结果和最大结束位置:
- 这一步的空间复杂度是 O(1)。
- 遍历排序后的区间:
- 这一步的空间复杂度是 O(1)。
综上所述,总的空间复杂度为: O(1)+O(1)+O(logn)+O(1)+O(1)=O(logn)
代码实现
Java代码实现
import java.util.Arrays;
public class Main {
public static int solution(int[][] inputArray) {
if (inputArray == null || inputArray.length < 1) return 0;
int n = inputArray.length;
// 特殊情况处理
if (n == 1) {
return inputArray[0][1] - inputArray[0][0] + 1;
}
// 按区间的起始位置排序
Arrays.sort(inputArray, (p, q) -> p[0] - q[0]);
// 初始化结果和最大结束位置
int res = inputArray[0][1] - inputArray[0][0] + 1;
int maxt = inputArray[0][1];
// 遍历排序后的区间
for (int i = 1; i < n; i++) {
if (inputArray[i][0] > maxt) {
// 当前区间与前一个区间不重叠
res += (inputArray[i][1] - inputArray[i][0] + 1);
} else if (inputArray[i][1] > maxt) {
// 当前区间与前一个区间部分重叠
res += (inputArray[i][1] - maxt);
}
// 更新最大结束位置
if (inputArray[i][1] > maxt) {
maxt = inputArray[i][1];
}
}
return res;
}
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);
}
}
Go 代码实现
package main
import (
"fmt"
"sort"
)
func solution(inputArray [][]int) int {
if inputArray == nil || len(inputArray) < 1 {
return 0
}
n := len(inputArray)
// 特殊情况处理
if n == 1 {
return inputArray[0][1] - inputArray[0][0] + 1
}
// 按区间的起始位置排序
sort.Slice(inputArray, func(i, j int) bool {
return inputArray[i][0] < inputArray[j][0]
})
// 初始化结果和最大结束位置
res := inputArray[0][1] - inputArray[0][0] + 1
maxt := inputArray[0][1]
// 遍历排序后的区间
for i := 1; i < n; i++ {
if inputArray[i][0] > maxt {
// 当前区间与前一个区间不重叠
res += (inputArray[i][1] - inputArray[i][0] + 1)
} else if inputArray[i][1] > maxt {
// 当前区间与前一个区间部分重叠
res += (inputArray[i][1] - maxt)
}
// 更新最大结束位置
if inputArray[i][1] > maxt {
maxt = inputArray[i][1]
}
}
return res
}
func main() {
// You can add more test cases here
testArray1 := [][]int{{1, 4}, {7, 10}, {3, 5}}
testArray2 := [][]int{{1, 2}, {6, 10}, {11, 15}}
fmt.Println(solution(testArray1) == 9)
fmt.Println(solution(testArray2) == 12)
}