豆包MarsCode AI刷题---打点计数器的区间合并

43 阅读4分钟

一:题目详细内容

问题描述

小明正在设计一台打点计数器,该计数器可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。小明需要你帮助他计算,在给定的多组数字范围内,计数器会打多少个点。

例如,给定三个数字范围 [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

题目中所给的代码:

public class Main { public static int solution(int[][] inputArray) { // Please write your code here return -2; } 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); } }

二:题目详细分析和解题

2.1 题目详细分析
题目要求设计一个打点计数器,该计数器接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。最后,需要计算在给定的多组数字范围内,计数器会打多少个点。

解决方案步骤

  1. 排序输入范围

    • 由于我们需要合并重叠的范围,因此首先按照范围的起始值对输入数组进行排序。
    • 排序后,我们可以更容易地遍历数组并检查相邻范围是否重叠。
  2. 合并重叠范围

    • 初始化一个用于存储合并后范围的数组。
    • 遍历排序后的输入数组,对于每个范围,检查它是否与上一个合并的范围重叠。
    • 如果重叠,则更新上一个合并范围的结束值,以包含当前范围的结束值(如果它更远)。
    • 如果不重叠,则将当前范围添加到合并后范围的数组中。
  3. 计算唯一数字的数量

    • 遍历合并后的范围数组,对于每个范围,计算其包含的唯一数字的数量。
    • 将所有范围的数字数量相加,得到总数。

2.2 代码详细实现

import java.util.Arrays; public class DotCounter { public static int countDots(int[][] inputRanges) { // 1. 排序输入范围 // 使用Lambda表达式定义比较器,按范围的起始值排序 Arrays.sort(inputRanges, (a, b) -> Integer.compare(a[0], b[0])); // 2. 合并重叠范围 // 初始化合并后范围的数组,大小与输入数组相同(最坏情况下所有范围都不重叠) int[][] mergedRanges = new int[inputRanges.length][2]; // mergeIndex用于跟踪合并后范围数组的实际大小 int mergeIndex = 0; // 将第一个范围添加到合并后范围的数组中 mergedRanges[mergeIndex] = inputRanges[0]; // 遍历输入数组,从第二个范围开始 for (int i = 1; i < inputRanges.length; i++) { int[] currentRange = inputRanges[i]; int[] lastMergedRange = mergedRanges[mergeIndex]; // 检查当前范围是否与上一个合并的范围重叠 // 重叠的条件是当前范围的起始值小于等于上一个合并范围的结束值+1 if (currentRange[0] <= lastMergedRange[1] + 1) { // 合并范围:更新上一个合并范围的结束值 // 使用Math.max确保结束值是两者中的最大值 lastMergedRange[1] = Math.max(lastMergedRange[1], currentRange[1]); } else { // 不重叠,将当前范围添加到合并后范围的数组中 mergeIndex++; mergedRanges[mergeIndex] = currentRange; } } // 3. 计算唯一数字的数量 int count = 0; // 遍历合并后的范围数组,计算每个范围的数字数量并累加 for (int i = 0; i <= mergeIndex; i++) { int[] range = mergedRanges[i]; // 数字数量等于范围结束值减去起始值加1 count += range[1] - range[0] + 1; } return count; } public static void main(String[] args) { // 测试样例 int[][] testArray1 = {{1, 4}, {7, 10}, {3, 5}}; int[][] testArray2 = {{1, 2}, {6, 10}, {11, 15}}; int[][] testArray3 = {{1, 3}, {2, 6}, {8, 10}}; // 打印测试结果 System.out.println(countDots(testArray1) == 9); // true System.out.println(countDots(testArray2) == 12); // true System.out.println(countDots(testArray3) == 9); // true } }
简单来说这个求解过程可以分为排序、合并、计算唯一数字的数量,最后返回打点数的个数。