题目描述:
给定一个包含 非负数 的数组和一个目标 整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,且总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数。
示例 1:
输入:[23,2,4,6,7], k = 6
输出:True
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6。
示例 2:
输入:[23,2,6,4,7], k = 6
输出:True
解释:[23,2,6,4,7]是大小为 5 的子数组,并且和为 42。
解答:
应用 (i - j) % k 恒等于 0. 等价于i % k == j % k。
将i,j 分别看做nums[i]的前缀和与nums[j]的前缀和。
将前缀和的余数作为hash key。 i,j 作为 hash value。当出现hash(i) = hash(j) 且 j - 2 >= 2即可。
注意哈希map的初始值设为hash(0) = -1.避免单独判断。
代码:
class Solution:
def checkSubarraySum(self, nums: List[int], k: int) -> bool:
cur_sum = 0
# remainder_map key: 前缀和%k 的余数
# remainder_map value: [0, i]的前缀和。则value为i
# 初始的remainder_map[0] = -1用得好。避免了只有一个元素时的单独判断。
remainder_map = dict({0: -1})
for i in range(len(nums)):
cur_sum += nums[i]
if k:
cur_sum %= k
if cur_sum in remainder_map and i - remainder_map[cur_sum] > 1:
return True
if cur_sum not in remainder_map:
remainder_map[cur_sum] = i
return False