Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to a multiple of k, that is, sums up to n*k where n is also an integer.
Example 1:
Input: [23, 2, 4, 6, 7], k=6 Output: True Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up to 6.
Example 2:
Input: [23, 2, 6, 4, 7], k=6 Output: True Explanation: Because [23, 2, 6, 4, 7] is an continuous subarray of size 5 and sums up to 42.
public boolean checkSubarraySum(int[] nums, int k) { if(nums.length == 0 || nums == null) return false; int n = nums.length; int[] prefix = new int[n + 1]; for(int i = 1; i <= n; i++) prefix[i] = prefix[i - 1] + nums[i - 1]; for(int i = 0; i < n; i++) { for(int j = i + 2; j <= n; j++) { if(k == 0) { if(prefix[j] - prefix[i] == 0) return true; } else if((prefix[j] - prefix[i]) % k == 0) return true; } } return false; }
O(n^2) 方法,把presum计算出来,然后分k=0/≠0找有没有合适的解
/** Key point: if we can find any two subarray of prefix sum have same mod value, then their difference MUST be * divisible by k. So we can use a map to store mod value of each prefix sum in map, with its index. Then check * if map contains the same mod value with size > 2 when we have new mod value in every iteration */ public boolean checkSubarraySum(int[] nums, int k) { if (nums.length < 2) { return false; } Map<Integer, Integer> map = new HashMap<>(); // corner case: if the very first subarray with first two numbers in array could form the result, we need to // put mod value 0 and index -1 to make it as a true case map.put(0, -1); int curSum = 0; for (int i = 0; i < nums.length; i++) { curSum += nums[i]; // corner case: k CANNOT be 0 when we use a number mod k if (k != 0) { curSum = curSum % k; } if (map.containsKey(curSum)) { if (i - map.get(curSum) > 1) { return true; } } else { map.put(curSum, i); } } return false; }
把presum 对 k 的mod和它的first index存到map里,为了应对k==0,要map.put(0, -1),然后在循环中持续检查即可