Java 中的范围和计数问题2025年3月17日 | 阅读11分钟 给定一个包含负数和非负数的数组 numArr[],大小为 S。还提供了两个数字 ‘left’ 和 ‘right’。我们的任务是返回区间和的数量,使得该和介于 left 和 right 之间(包括 left 和 right),其中 left <= right。区间和 R(l, r) 表示 numArr[] 中索引 l 到 r 之间的数字之和,其中 l 必须小于或等于 r。 示例 1输入: numArr[] = {1, 2, 3, 4, 5, 6, 7}, left = 2, right = 7 输出: 有 10 个区间,其和介于 2 和 7 之间。 解释: 让我们看看不同子数组的区间和。 从第 0 个索引开始 R[0, 0] 为 1 = 1 R[0, 1] = 1 + 2 = 3 R[0, 2] = 1 + 2 + 3 = 6 R[0, 3] = 1 + 2 + 3 + 4 = 10 R[0, 4] = 1 + 2 + 3 + 4 + 5 = 15 R[0, 5] = 1 + 2 + 3 + 4 + 5 + 6 = 21 R[0, 6] = 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28 从第 1 个索引开始 R[1, 1] 为 2 = 2 R[1, 2] = 2 + 3 = 5 R[1, 3] = 2 + 3 + 4 = 9 R[1, 4] = 2 + 3 + 4 + 5 = 14 R[1, 5] = 2 + 3 + 4 + 5 + 6 = 20 R[1, 6] = 2 + 3 + 4 + 5 + 6 + 7 = 27 从第 2 个索引开始 R[2, 2] 为 3 = 3 R[2, 3] = 3 + 4 = 7 R[2, 4] = 3 + 4 + 5 = 12 R[2, 5] = 3 + 4 + 5 + 6 = 18 R[2, 6] = 3 + 4 + 5 + 6 + 7 = 25 从第 3 个索引开始 R[3, 3] 为 4 = 4 R[3, 4] = 4 + 5 = 9 R[3, 5] = 4 + 5 + 6 = 15 R[3, 6] = 4 + 5 + 6 + 7 = 22 从第 4 个索引开始 R[4, 4] 为 5 = 5 R[4, 5] = 5 + 6 = 11 R[4, 6] = 5 + 6 + 7 = 18 从第 5 个索引开始 R[5, 5] 为 6 = 6 R[5, 6] = 6 + 7 = 13 从第 6 个索引开始 R[6, 6] 为 7 = 7 下图显示了相同的情况。 ![]() 在所有这些区间中,只有 R[0, 1], R[0, 2], R[1, 1], R[1, 2], R[2, 2], R[2, 3], R[3, 3], R[4, 4], R[5, 5], 和 R[6, 6] 介于 2 到 7 之间。因此,总共有 7 个区间和在 2 到 7 之间(包括两端)。因此,答案是 7。 示例 2输入: numArr[] = {11, 12, 13, 14, 15, 16, 17}, left = 9, right = 10 输出: 没有区间的和介于 13 和 20 之间。 解释: 让我们看看不同子数组的区间和。 从第 0 个索引开始 R[0, 0] 为 11 = 11 R[0, 1] = 11 + 12 = 23 R[0, 2] = 11 + 12 + 13 = 36 R[0, 3] = 11 + 12 + 13 + 14 = 50 R[0, 4] = 11 + 12 + 13 + 14 + 15 = 65 R[0, 5] = 11 + 12 + 13 + 14 + 15 + 16 = 81 R[0, 6] = 11 + 12 + 13 + 14 + 15 + 16 + 17 = 98 从第 1 个索引开始 R[1, 1] 为 12 = 12 R[1, 2] = 12 + 13 = 25 R[1, 3] = 12 + 13 + 14 = 39 R[1, 4] = 12 + 13 + 14 + 15 = 54 R[1, 5] = 12 + 13 + 14 + 15 + 16 = 70 R[1, 6] = 12 + 13 + 14 + 15 + 16 + 17 = 87 从第 2 个索引开始 R[2, 2] 为 13 = 13 R[2, 3] = 13 + 14 = 27 R[2, 4] = 13 + 14 + 15 = 42 R[2, 5] = 13 + 14 + 15 + 16 = 58 R[2, 6] = 13 + 14 + 15 + 16 + 17 = 75 从第 3 个索引开始 R[3, 3] 为 14 = 14 R[3, 4] = 14 + 15 = 29 R[3, 5] = 14 + 15 + 16 = 45 R[3, 6] = 14 + 15 + 16 + 17 = 62 从第 4 个索引开始 R[4, 4] 为 15 = 15 R[4, 5] = 15 + 16 = 31 R[4, 6] = 15 + 16 + 17 = 48 从第 5 个索引开始 R[5, 5] 为 16 = 16 R[5, 6] = 16 + 17 = 33 从第 6 个索引开始 R[6, 6] 为 17 = 17 下图显示了相同的情况。 ![]() 在所有这些区间中,没有一个区间的和介于 9 到 10 之间。因此,总共有 0 个区间和在 9 到 10 之间(包括两端)。 朴素方法直接或朴素的方法是找出输入数组的所有子数组。之后,过滤掉那些和在(left 到 right)范围内的子数组。 算法步骤 1: 初始化变量 count = 0, tmp = 0。 步骤 2: 迭代 j 从 0 到输入数组的长度 - 1。这是为了确定我们子数组的起始点。
步骤 3: 返回 count。 实施观察上述算法的实现。 文件名: CountRangeSum.java 输出 For the input array: 1 2 3 4 5 6 7 The number of ranges whose sum lies between 2 & 7 is 10. For the input array: 11 12 13 14 15 16 17 There is no range whose sum lies between 9 & 10. 复杂度分析: 我们使用了嵌套的 for 循环来计算答案。因此,程序的 time complexity 为 O(n2),其中 n 是数组中元素的总数。另外,我们没有使用任何数据结构来保存结果。因此,程序的 space complexity 是常数,即 O(1)。 高效方法在此方法中,我们将尝试将程序的 time complexity 从 O(n2) 降低。在此解决方案中,借助归并排序,我们在归并过程中计算答案。在归并阶段,我们已经对左半部分 [start, mid) 和右半部分 [mid, end) 进行了排序。然后我们用索引 i 遍历左半部分。对于每个 i,需要计算右半部分中的两个索引 m 和 n,其中 n 是第一个满足 sumArr[n] - sumArr[i] <= right 的索引,k 是第一个满足 sumArr[m] - sumArr[i] < left 的索引。那么,[left, right] 中的总和数为 n - m。 观察以下算法。 算法步骤 1: 定义一个方法,该方法使用归并排序计算和在范围 [left, right] 内的子数组的数量,该方法为 int mergeCount(int sumArr[], int left, int right, int st, int ed)。 步骤 2: 处理基本情况:当 ed - st <= 1 时,返回 0。 步骤 3: 初始化一些变量 int mid = (st + ed) / 2; int m = mid; int n = mid; 步骤 4: 初始化另一个名为 count 的变量,并将 count 更新为,count = mergeCount (sumArr, left, right, st, mid) + mergeCount(sumArr, left, right, mid, ed) 步骤 5: 迭代 j 从 st 到 mid。 While(m < ed and sumArr[m] - sumArr[j] < left) m = m + 1; while(n < ed and sumArr[n] - sumArr[j] <= right) n = n + 1; 将 count 更新为 count = count + n - m。 步骤 6: 对 sumArr 从 st 到 ed 进行排序。 步骤 7: 返回 count。 实施观察上述算法的实现。 文件名: CountRangeSum1.java 输出 For the input array: 1 2 3 4 5 6 7 The number of ranges whose sum lies between 2 & 7 is 10. For the input array: 11 12 13 14 15 16 17 There is no range whose sum lies between 9 & 10. 复杂度分析: 我们使用了归并排序技术。因此,上述程序的 time complexity 为 O(n * log(n))。另外,我们使用了辅助数组 sumArr[]。因此,上述程序的 space complexity 为 O(n),其中 n 是输入数组中元素的总数。 下一个主题Java 中创建互质树 |
我们请求您订阅我们的新闻通讯以获取最新更新。