最后更新于
最后更新于
给定一个包含 非负数 的数组和一个目标 整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,且总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数。
示例 1:
示例 2:
说明:
数组的长度不会超过 10,000 。
你可以认为所有数字总和在 32 位有符号整数范围内。
对于每个位置, 我们要寻找以其作为结尾的所有连续子数组中, 和是的正数倍的. 在中, 每个位置, 我们寻找的是以其作为结尾的所有连续子数组中, 和的值为的. 所以本题中我们可以转变一下思路, 还是使用前缀和, 但前缀和不再存储原始的和值, 而是存储前缀和对的余数, 这样对于某个位置, 我们求得其前缀和的余数为, 只需要找之前的前缀中, 是否有余数也为的位置, 且这两个位置之差至少为2, 如果满足, 就找到了满足条件的子数组.
需要注意几点:
哈希表的key值为前缀和的余数, 值为这个余数第一次出现的位置; 后面再次遇到, 判断距离即可
其实上面的代码中有个bug
, 对于nums=[3,0,0,0,0], k=6
这种测试用例, 也是会返回True
的. 但在Leetcode
可以通过, 说明其用例也没有考虑这种情况. 正确的做法应当是哈希表中除了位置, 还要记录总值大小, 这样在余数相等时, 还要再比较两个位置前缀和的总大小是否相等. 这样, total
的更新规则也要改变.
对于余数为0的情况, 即可以整除, 就可能产生了答案, 无需再向下走. 因此, 不能遇到这种情况, 再向哈希表中添加余数为0的位置, 这样可能错过正确的答案. 因此在初始化哈希表时, 向其中添加0: -1
的键值对. 这样如果数组的前两个位置之和是的正整数倍, 就产生了结果
由于我们只关心余数, 因此不需要记录真正的前缀和, 而是一直记录前缀和余数, 对于新的位置, 前一步的余数加上这个值, 再求对的余数, 这样得到的余数就是正确的