【华为OD-E卷 - 数组连续和 100分(python、java、c++、js、c)】
题目
给定一个含有N个正整数的数组, 求出有多少个连续区间(包括单个正整数), 它们的和大于等于x
输入描述
- 第一行两个整数N x(0 < N <= 100000, 0 <= x <= 10000000)
第二行有N个正整数(每个正整数小于等于100)
输出描述
- 输出一个整数,表示所求的个数
备注
- 注意:此题对效率有要求,暴力解法通过率不高,请考虑高效的实现方式
用例
用例一:
输入:
3 7
3 4 7
输出:
4
用例二:
输入:
10 10000
1 2 3 4 5 6 7 8 9 10
输出:
0
python解法
- 解题思路:
- 这道题的目标是计算数组中满足子数组和大于等于给定值 x 的子数组数量。以下是解题的基本思路:
双层循环遍历:
外层循环选择子数组的起始点 i。
内层循环选择子数组的结束点 j,计算从 i 到 j 的子数组和 total。
提前终止内层循环:
一旦找到一个子数组的和 total 大于等于 x,就可以确定从 j 开始到数组末尾的所有子数组都满足条件。原因是这些子数组都以 i 为起点,而子数组越长,和只会更大。
优化:
当找到第一个满足条件的 j 后,直接计算满足条件的子数组数量 N - j,并结束内层循环
def count_subarrays(N, x, nums):
# 初始化满足条件的子数组计数器
count = 0
# 遍历数组的每个起始点
for i in range(N):
# 初始化当前子数组的和
total = 0
# 遍历从起始点到末尾的所有子数组
for j in range(i, N):
total += nums[j] # 累加当前子数组的和
# 如果当前子数组的和 >= x,计算满足条件的子数组数量
if total >= x:
count += N - j # 从 j 开始到数组末尾的子数组都满足条件
break # 结束内层循环,跳到下一个起始点
return count # 返回满足条件的子数组总数
if __name__ == "__main__":
import sys
# 读取标准输入的多行数据
input_lines = sys.stdin.read().strip().splitlines()
# 解析第一行,得到数组长度 N 和目标值 x
N, x = map(int, input_lines[0].split())
# 解析第二行,得到数组 nums
nums = list(map(int, input_lines[1].split()))
# 调用函数并输出结果
print(count_subarrays(N, x, nums))
java解法
- 解题思路
- 这道题的目标是计算数组中满足子数组和大于等于给定值 limit 的子数组数量。为了解决问题,我们使用 滑动窗口 技巧来高效计算:
滑动窗口的概念:
通过两个指针 start 和 end 来定义一个窗口,窗口表示当前子数组的范围。
指针 end 用于扩展窗口,增加子数组的范围。
指针 start 用于收缩窗口,排除不必要的元素,保证子数组和小于 limit。
操作逻辑:
每次将 values[end] 加入当前窗口的和 sum。
如果 sum 大于等于 limit,说明从 start 到 end 的子数组满足条件,而对于当前 end,从 start 到数组末尾的子数组也都满足条件,可以直接计算这些子数组的数量:num - end。
然后收缩窗口,即移动 start 指针并从 sum 中减去 values[start]。
优化:
通过滑动窗口,只需遍历每个元素一次(每个元素最多被加入和移除一次),时间复杂度为