zoukankan      html  css  js  c++  java
  • [LeetCode] 974. Subarray Sums Divisible by K 子数组数字之和可被K整除


    Given an array A of integers, return the number of (contiguous, non-empty) subarrays that have a sum divisible by K.

    Example 1:

    Input: A = [4,5,0,-2,-3,1], K = 5
    Output: 7
    Explanation: There are 7 subarrays with a sum divisible by K = 5:
    [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
    

    Note:

    1. 1 <= A.length <= 30000
    2. -10000 <= A[i] <= 10000
    3. 2 <= K <= 10000

    这道题给了一个数组,让返回数组的数字之和可以被K整除的非空子数组的个数。博主最开始的思路是建立累加和数组,然后就可以快速的知道任意一个子数组的数字和,从而可以判断其是否可以被K整除。但是这个方法被 OJ 残忍拒绝,说是超时 TLE 了,看来需要进一步的将平方级的复杂度优化到线性复杂度才行。说到查询的线性复杂度,那么 HashMap 是当仁不让的,可是这里该如何利用它呢。这里首先要搞懂一个规律,若子数组 [0, i] 的数字之和跟子数组 [0, j] 的数字之和对K取余相同的话,假设这里 j > i,那么子数组 [i+1, j] 的数字之和一定是可以整除K的。这里就不证明了,举个例子吧,比如 [1, 2, 3, 4],K=5,那么 [1] 之和除以5余1,[1, 2, 3] 之和除以5也余1,则 [2, 3] 之和一定可以整除5。有了这些知识,就可以建立数组和除以K的余数跟其出现次数之间的映射了,注意由于数组中可能出现负数,而我们并不希望出现负余数,所以先对K余数,然后再加个K,再对K取余数,这样一定可以得到正余数。在声明了 HashMap 后,初始化时要把 0 -> 1 先放进去,原因在后面会讲。同时新建变量 sum,用来保存当前的数组和对K的余数,遍历数组A中的数字 num,根据之前说的,num 先对K取余,然后再加上K,之和再加上 sum,再对K取余。此时将 sum 对映射值加到结果 res 中,这里就有两种情况,一种是 sum 并不存在,这样映射值默认是0,另一种是 sum 存在,则根据之前的规律,一定可以找到相同数目的子数组可以整除K,所以将映射值加入结果 res,同时要将 sum 的映射值自增1。这里解释一下为啥刚开始初始化0的映射值是1,因为若 sum 正好是0了,则当前的数组就是符合的题意的,若0的映射值不是1,则这个数组就无法被加入到结果 res 中,参见代码如下:


    解法一:

    class Solution {
    public:
        int subarraysDivByK(vector<int>& A, int K) {
        	int res = 0, sum = 0;
            unordered_map<int, int> m{{0, 1}};
            for (int num : A) {
            	sum = (sum + num % K + K) % K;
            	res += m[sum];
            	++m[sum];
            }
            return res;
        }
    };
    

    由于K的余数个数是确定的,所以也可以用个数组来代替 HashMap,其他的部分没啥区别,解题思想也和上面完全一样,参见代码如下:


    解法二:

    class Solution {
    public:
        int subarraysDivByK(vector<int>& A, int K) {
        	int res = 0, sum = 0;
            vector<int> cnt(K);
            cnt[0] = 1;
            for (int num : A) {
            	sum = (sum + num % K + K) % K;
            	res += cnt[sum];
            	++cnt[sum];
            }
            return res;
        }
    };
    

    Github 同步地址:

    https://github.com/grandyang/leetcode/issues/974


    类似题目:

    Subarray Sum Equals K

    Make Sum Divisible by P


    参考资料:

    https://leetcode.com/problems/subarray-sums-divisible-by-k/

    https://leetcode.com/problems/subarray-sums-divisible-by-k/discuss/217985/JavaC%2B%2BPython-Prefix-Sum

    https://leetcode.com/problems/subarray-sums-divisible-by-k/discuss/217980/Java-O(N)-with-HashMap-and-prefix-Sum


    LeetCode All in One 题目讲解汇总(持续更新中...)

  • 相关阅读:
    About try...expect...else
    About from __future__ import absolute_import
    How to 安装apache和配置自定义目录, run CGI or py
    Caffe
    About os.environ
    TensorFlow
    Keras
    SQL自定义函数,把sql中小数点后的多于0去掉
    .net杂记 (调用EXE 获取路径 target VB DIV C# Split 页面之间传递值 更改session时间 EXCEL操作 控制电子邮件Mail input记录值的窍门)
    orcle分析函数
  • 原文地址:https://www.cnblogs.com/grandyang/p/14163228.html
Copyright © 2011-2022 走看看