327. 区间和的个数
原始题目链接:https://leetcode.cn/problems/count-of-range-sum/
给你一个整数数组 nums 以及两个整数 lower 和 upper 。求数组中,值位于范围 [lower, upper] (包含 lower 和 upper)之内的 区间和的个数 。
区间和 S(i, j) 表示在 nums 中,位置从 i 到 j 的元素之和,包含 i 和 j (i ≤ j)。
示例 1:
输入:nums = [-2,5,-1], lower = -2, upper = 2
输出:3
解释:存在三个区间:[0,0]、[2,2] 和 [0,2] ,对应的区间和分别是:-2 、-1 、2 。
示例 2:
输入:nums = [0], lower = 0, upper = 0
输出:1
解题思路:
满足一定条件的区间和的个数,使用前缀和 +
二分查找的方式进行求解。这道题使用数学转换的方法进行了条件变化,来进行判断。具体实现看代码及注释。
代码实现:
import bisect
class Solution:
def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:
# 存储数组nums的前缀和,sorted_pre_nums[i]表示从起点到i的所有元素之和
sorted_pre_nums = [0]
ans = 0
pre_sum = 0
for num in nums:
pre_sum += num
# 题目要求找到满足:lower <= sorted_pre_nums[j] - sorted_pre_nums[i] <= upper 条件的前缀和个数
# 进行数学变换:sorted_pre_nums[j] - upper <= sorted_pre_nums[i] <= sorted_pre_nums[j] - lower
# 所以在遍历当前数组元素位置j的之前的所有位置i,满足变换后的条件的i,都是符合题意的解
# 所以一趟遍历下来,解的个数是 r - l
l = bisect.bisect_left(sorted_pre_nums, pre_sum - upper)
r = bisect.bisect_right(sorted_pre_nums, pre_sum - lower)
ans += r - l
# 把当前的前缀和加入到有序数组中
bisect.insort(sorted_pre_nums, pre_sum)
return ans
参考文献:
https://leetcode.cn/problems/count-of-range-sum/solution/qian-zhui-he-jia-er-fen-cha-zhao-by-amchor/