LeetCode //C - 327. Count of Range Sum

327. Count of Range Sum

Given an integer array nums and two integers lower and upper, return the number of range sums that lie in [lower, upper] inclusive.

Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j inclusive, where i <= j.

Example 1:

Input: nums = [-2,5,-1], lower = -2, upper = 2
Output: 3
Explanation: The three ranges are: [0,0], [2,2], and [0,2] and their respective sums are: -2, -1, 2.

Example 2:

Input: nums = [0], lower = 0, upper = 0
Output: 1

Constraints:
  • 1 < = n u m s . l e n g t h < = 1 0 5 1 <= nums.length <= 10^5 1<=nums.length<=105
  • − 2 31 < = n u m s [ i ] < = 2 31 − 1 -2^{31} <= nums[i] <= 2^{31} - 1 −231<=nums[i]<=231−1
  • − 1 0 5 < = l o w e r < = u p p e r < = 1 0 5 -10^5 <= lower <= upper <= 10^5 −105<=lower<=upper<=105
  • The answer is guaranteed to fit in a 32-bit integer.

From: LeetCode

Link: 327. Count of Range Sum


Solution:

Ideas:
  1. Prefix Sum Array: We create a prefix sum array where prefixSums[i] represents the sum of the array elements from the start to the i-th index. This allows us to calculate the sum of any subarray [i, j] as prefixSums[j+1] - prefixSums[i].

  2. Merge Sort: The core idea of the solution is to use a modified merge sort. During the merge step, we count the number of valid ranges [i, j] that satisfy the condition lower <= S(i, j) <= upper. This is done by maintaining the order of the prefix sums while counting how many sums in the right half of the array fall within the desired range relative to each sum in the left half.

  3. Counting with Binary Search: Within the merge step, we use two pointers to determine the range [lower, upper] for each prefix sum in the left half compared to prefix sums in the right half. This ensures that the solution remains efficient even for large arrays.

Code:
c 复制代码
long* temp;

int mergeCount(long* prefixSums, int left, int right, int lower, int upper) {
    if (left >= right) {
        return 0;
    }
    
    int mid = left + (right - left) / 2;
    int count = mergeCount(prefixSums, left, mid, lower, upper) + mergeCount(prefixSums, mid + 1, right, lower, upper);
    
    int j = mid + 1, k = mid + 1, t = mid + 1;
    int r = 0;
    
    for (int i = left; i <= mid; ++i) {
        while (j <= right && prefixSums[j] - prefixSums[i] < lower) j++;
        while (k <= right && prefixSums[k] - prefixSums[i] <= upper) k++;
        while (t <= right && prefixSums[t] < prefixSums[i]) temp[r++] = prefixSums[t++];
        temp[r++] = prefixSums[i];
        count += k - j;
    }
    
    for (int i = 0; i < t - left; ++i) {
        prefixSums[left + i] = temp[i];
    }
    
    return count;
}

int countRangeSum(int* nums, int numsSize, int lower, int upper) {
    if (numsSize == 0) {
        return 0;
    }
    
    long* prefixSums = (long*)malloc((numsSize + 1) * sizeof(long));
    temp = (long*)malloc((numsSize + 1) * sizeof(long));
    
    prefixSums[0] = 0;
    for (int i = 0; i < numsSize; ++i) {
        prefixSums[i + 1] = prefixSums[i] + nums[i];
    }
    
    int result = mergeCount(prefixSums, 0, numsSize, lower, upper);
    
    free(prefixSums);
    free(temp);
    
    return result;
}
相关推荐
浮生如梦_1 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
励志成为嵌入式工程师3 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
师太,答应老衲吧3 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer3 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
wheeldown4 小时前
【数据结构】选择排序
数据结构·算法·排序算法
hikktn5 小时前
如何在 Rust 中实现内存安全:与 C/C++ 的对比分析
c语言·安全·rust
观音山保我别报错5 小时前
C语言扫雷小游戏
c语言·开发语言·算法
TangKenny6 小时前
计算网络信号
java·算法·华为