题目:
给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:
子数组大小 至少为 2 ,且
子数组元素总和为 k 的倍数。
如果存在,返回 true ;否则,返回 false 。
如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 x 是 k 的一个倍数。0 始终视为 k 的一个倍数。
示例 1:
输入:nums = [23,2,4,6,7], k = 6
输出:true
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6 。
示例 2:
输入:nums = [23,2,6,4,7], k = 6
输出:true
解释:[23, 2, 6, 4, 7] 是大小为 5 的子数组,并且和为 42 。
42 是 6 的倍数,因为 42 = 7 * 6 且 7 是一个整数。
示例 3:
输入:nums = [23,2,6,4,7], k = 13
输出:false
提示:
1 <= nums.length <= 105
0 <= nums[i] <= 109
0 <= sum(nums[i]) <= 231 - 1
1 <= k <= 231 - 1
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/continuous-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
前缀和+HashMap:
1.计算前缀和,创建一个HashMap,其中的key为前缀和对k取余后是余数,value为对应的index索引位置;
2.如果在哈希表中存在有当前相同的前缀余数,取出其value,并且与当前index距离大于等于2,则说明符合题目要求,返回true,如果小于2,则继续遍历;
3.如果不存在则将当前余数与其对应的下标index存储在哈希表中。
图来自@小虎
注意:加入map.put(0, -1)是为了把边界值也考虑进入,不用在特殊考虑。
java代码:
1 class Solution { 2 public boolean checkSubarraySum(int[] nums, int k) { 3 Map<Integer, Integer> map = new HashMap<>(); 4 map.put(0, -1); 5 int prefixsum = 0, rem = 0; 6 for(int i = 0; i < nums.length; i++){ 7 prefixsum += nums[i]; 8 rem = prefixsum % k; 9 if(map.containsKey(rem)){ 10 if(i - map.get(rem) >= 2){ 11 return true; 12 } 13 }else{ 14 map.put(rem, i); 15 } 16 } 17 return false; 18 } 19 }
python代码:
1 class Solution: 2 def checkSubarraySum(self, nums: List[int], k: int) -> bool: 3 map = {} 4 map[0] = -1 5 prefixSum, rem = 0, 0 6 for i in range(len(nums)): 7 prefixSum += nums[i] 8 rem = prefixSum % k 9 if rem in map: 10 if (i - map[rem] >= 2): 11 return True 12 else: 13 map[rem] = i 14 return False