描述
给定一个数组和一个范围,求子数组的和在这个范围的所有子数组数。
思路
暴力枚举,O(n^2)超时:
from typing import (
List,
)
class Solution:
"""
@param a: An integer array
@param start: An integer
@param end: An integer
@return: the number of possible answer
"""
def subarray_sum_i_i(self, a: List[int], start: int, end: int) -> int:
ans = 0
for i in range(len(a)):
tmp = 0
for j in range(i, len(a)):
tmp += a[j]
if tmp>end:
break
if tmp>=start and tmp<=end:
ans += 1
return ans
two pointers,通过。O(n)时间复杂度,O(n)空间复杂度。
首先记录前缀和。
假设数组a为题目给的数组,[start,end]为题目给的范围。
遍历数组a,尝试以当前元素a[i]为起始,向右找,找到第一个元素a[l],使得从a[i]到a[l]的子数组的和等于或大于start。
从数组a的末尾往左找,找到第一个元素a[r],使得从a[i]到a[r]的子数组的和小于或等于end。
如果没找到a[l]或a[r]就退出遍历,因为现在没找到,以后更找不到,这是由前缀和的特性决定的。
from typing import (
List,
)
class Solution:
"""
@param a: An integer array
@param start: An integer
@param end: An integer
@return: the number of possible answer
"""
def subarray_sum_i_i(self, a: List[int], start: int, end: int) -> int:
n = len(a)
ans = 0
if n == 0:
return 0
pre_sum = [0 for i in range(n+1)]
for i in range(1, n+1):
pre_sum[i] = pre_sum[i-1] + a[i-1]
for i in range(1, n+1):
l=i
while l<n and pre_sum[l]-pre_sum[i]+a[i-1]<start:
l += 1
if pre_sum[l]-pre_sum[i]+a[i-1]<start:
break
r=n
while l<r and pre_sum[r]-pre_sum[i]+a[i-1]>end:
r -= 1
if pre_sum[r]-pre_sum[i]+a[i-1]>end:
break
ans += r-l+1
print(ans)
return ans