[LeetCode] 523. Continuous Subarray Sum

Given an integer array nums and an integer k, return true if nums has a good subarray or false otherwise.

A good subarray is a subarray where:
its length is at least two, and
the sum of the elements of the subarray is a multiple of k.

Note that:
A subarray is a contiguous part of the array.
An integer x is a multiple of k if there exists an integer n such that x = n * k. 0 is always a multiple of k.

Example 1:
Input: nums = [23,2,4,6,7], k = 6
Output: true
Explanation: [2, 4] is a continuous subarray of size 2 whose elements sum up to 6.

Example 2:
Input: nums = [23,2,6,4,7], k = 6
Output: true
Explanation: [23, 2, 6, 4, 7] is an continuous subarray of size 5 whose elements sum up to 42.
42 is a multiple of 6 because 42 = 7 * 6 and 7 is an integer.

Example 3:
Input: nums = [23,2,6,4,7], k = 13
Output: false

Constraints:
1 <= nums.length <= 105
0 <= nums[i] <= 109
0 <= sum(nums[i]) <= 231 - 1
1 <= k <= 231 - 1

连续的子数组和。

给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:

子数组大小 至少为 2 ,且
子数组元素总和为 k 的倍数。
如果存在,返回 true ;否则,返回 false 。

如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 x 是 k 的一个倍数。0 始终视为 k 的一个倍数。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/continuous-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

题意是给定一个包含非负数的数组和一个目标整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数。

思路是前缀和。注意题目的要求,子数组的长度至少为 2,所以类似如下这样的情形,应该是要 return false 的。

input: [0], k = 0

既然是前缀和的思路,所以还是需要创建一个 hashmap,存前缀和以及当前这个前缀和第一次出现的下标。既然是找 sum 为 k 的倍数,所以自然而然想到取模的操作。注意这里有一个关于取模的公式需要知道(引用)。如果 sum[j] - sum[i] = n * k, 那么两边同时除以 k 我们可以得到 sum[j] / k - sum[i] / k = n。如果要使这个等式成立,我们需要满足 sum[j] % k == sum[i] % k。

所以我们在得到每一个前缀和之后,我们做 sum %= k,把余数当做 key 存入 hashmap。当我们再次遇到一个相同的 key 的时候,我们再判断这个 key 上一次出现的位置是否在两个位置以外即可。

另外一道跟前缀和 + 取模有关的题是 974 题。

复杂度

时间O(n)
空间O(n)

代码

Java实现

class Solution {
    public boolean checkSubarraySum(int[] nums, int k) {
        int n = nums.length;
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, -1);
        int sum = 0;
        int res = 0;
        for (int i = 0; i < n; i++) {
            int num = nums[i];
            sum = (sum + num) % k;
            if (sum < 0) {
                sum += k;
            }
            if (map.containsKey(sum)) {
                int lastIndex = map.get(sum);
                if (i - lastIndex >= 2) {
                    return true;
                }
            } else {
                map.put(sum, i);
            }
        }
        return false;
    }
}

JavaScript实现

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {boolean}
 */
var checkSubarraySum = function(nums, k) {
    let sum = 0;
    let map = new Map();
    map.set(0, -1);
    for (let i = 0; i < nums.length; i++) {
        sum += nums[i];
        if (k !== 0) {
            sum %= k;
        }
        let prev = map.get(sum);
        if (prev !== undefined) {
            if (i - prev > 1) {
                return true;
            }
        } else {
            map.set(sum, i);
        }
    }
    return false;
};

相关题目

523. Continuous Subarray Sum
974. Subarray Sums Divisible by K
posted @ 2020-04-15 03:29  CNoodle  阅读(189)  评论(0编辑  收藏  举报