官方最优解
- 前缀
ans = 0
for i in range(len(nums)):
sum = 0
for j in range(i, -1, -1):
# j: i -> 0,相当于计算前i个数的和
# 在计算前i个数的和的过程中,可能会出现sum == k的情况
sum += nums[j]
if sum == k :
count += 1
但这种方法时间复杂度高,为O(n^2)
换种思路,既然sum==k是出现在计算j的过程中
我们转换为都计算前缀,然后把结尾为i的前缀 - 结尾为j的前缀,
如果结果等于k那就说明存在这样的子数组
即 k = pre[i] - pre[j]
也即pre[j] = pre[i] - k
那我们就统计每种前缀和的个数就好了,并在统计的过程中查找是否有pre[j]的存在即可
class Solution(object):
def subarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
hash = collections.defaultdict(int)
pre_i = 0
count = 0
hash[0] = 1
n = len(nums)
for i in range(n):
pre_i += nums[i]
# 统计所有的前缀和的个数
# hash[sum] += 1 这个不能放这里,因为nums=[1], k =0时,会输出1
# 需要考虑一种情况,就是sum - k = 0,说明此时二者相等啊,
# 那count就应该+1, 所以就必须要设定hash[0] = 1
# 其他情况sum-k in hash,说明前j-1段是存在的,
# 那就需要统计hash表里面的键为sum-k的值
if (pre_i - k) in hash:
count += hash[pre_i - k]
# 统计所有的前缀和的个数
hash[pre_i] += 1
return count
# nums=[1,1,1] k=2
- 同理,我也可以试试 后缀解法
class Solution(object):
def subarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
n = len(nums)
hash = collections.defaultdict(int)
post_i = 0
count = 0
hash[0] = 1
for i in range(n-1, -1, -1):
post_i += nums[i]
if post_i - k in hash:# 说明post_j是在hash里面的
# count += 1
# 加的应该是post_j对应的值的个数
count += hash[post_i - k]
hash[post_i] += 1
return count
超出时间限制!!!
我的方法是
O
(
n
2
)
O(n^2)
O(n2)啊,应该也还行吧
- 这个是从前面往末尾加,相当于计算后缀
class Solution(object):
def subarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
# nums = sorted(nums) # 因为人家说的子串必须是连续的,所以不能sorted
n = len(nums)
ans = 0
for i in range(n):
s = nums[i]
j = i+1
if s == k:
ans += 1
# while s != k and j < n : #不能有s!=k,因为也许下一个也是0,不影响结果
# nums = [1, -1, 0], k = 0
while j < n:
s += nums[j]
j += 1
if s == k:
ans += 1
return ans
官网解法1
也超时了,因为它的时间复杂度也是 O ( n 2 ) O(n^2) O(n2)
- 从后面往前面加,相当于计算前缀
class Solution(object):
def subarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
count = 0
for i in range(len(nums)):
s = 0
for j in range(i, -1, -1):
s += nums[j]
if s == k:
count += 1
return count