[523]连续的子数组和 | continuous-subarray-sum

face.jpg

/*
Sologala @github https://github.com/Sologala/LeetCode.git

[523]连续的子数组和
| continuous-subarray-sum

*/

给定一个包含非负数的数组和一个目标整数 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。

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

Solution

方法1

​ 暴力枚举所有的部分和看是否能够整除 k 能过但是时间复杂度很高O(n^2)

O(n)解法
1.核心思想

​ 首先我们来观察一下这一组数据 [23,2,4,6,7] k = 6

//数组:		[23 , 2 , 4 , 6 , 7]
//累加:	    [23 , 25, 29, 35,42]
//余数:		[5  , 1 , 5 , 5 , 5]

通过以上的数据我们可以发现 数组的累加和对于K 的余数 当重复出现的时候就已经出现了 [2,4] 的和为 k = 6. 因此我们可以使用hash 来统计当前这个余数出现的次数,一旦发现出现了2次就可以 判断成立了 .

​ 2.从 0 开始的累加和已经构成 k 的倍数
有可能当前我们的累加和就正好是 `k` 的倍数,或者有累加和等于`0`,那么我们可以直接返回`true` 因为 **`0 * k = 0`**
​ 3. k == 1

​ 如果 k == 1 的情况下,我们 可以直接返回 true 因为 无论累加和是什么我们都可以通过 1 * n 计算出来.

​ 4. k == 0

k == 0 k 是有可能等于 0 的,那么这个时候是不能直接使用我们最刚开始发现的规律,因为 k = 0 是不能作为分母求余数的.这个时候我们选取 K = 1000000007 使得每次求余之后的结果都保存在 int 的范围内.这样问题就变成了一个累加和的问题,虽然这里的求余已经意义不大,但是好在代码不用更改太多.

​ 5. 类似这样的数据 [0,1,0] , k = 0

​ 这样的数据我们目前的代码是过不了的,当计算到最后一个 0 的时候他会觉得之前已经出现过了 余数1 ,于是直接返回了 true , 为了解决这个问题 ,我们需要使用 hash 存储是否出现 的时候存下当前的下标,如果我们判断已经出现过之后,还要追加判断是否距离超过1 ,这样才能说明已经出现了.

​ 6. k 为 负值

​ 这个时候处理一下就行了

k = k< 0 ? - k : k ;

以上就是所有的坑点,提交了 15 次踩出来的 (捂头抹泪~~)

执行用时 :28 ms, 在所有 C++ 提交中击败了99.29%的用户

内存消耗 :11.4 MB, 在所有 C++ 提交中击败了46.10%的用户

ac_code

class Solution {
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        unordered_map<int,int> m;
        if(nums.size()<=1) return false;
        k = (k < 0? -k : k);
        if(k==1) return true;
        k = (k == 0 ? 1000000007 : k);
        int cur =0;
        for(int i = 0;i<nums.size();++i){
            cur =  (cur + nums[i]);
            if((cur== k||cur==0)&&i>0) return true;
            int idx = m[cur%k];
            if(idx)
            {
                if(i - idx + 1 > 1) return true;
            }
            else m[cur%k] = i + 1;//这里我存储的是 从1开始为了避免 0 
        }
        return cur == 0;
    }
};

你可能感兴趣的:(LeetCode)