【问题标题】:Intuition behind storing the remainders?存储余数的直觉?
【发布时间】:2018-03-25 00:44:20
【问题描述】:

我正在尝试解决LeetCode.com 上的问题:

给定一个非负数列表和一个目标整数k,编写一个函数来检查数组是否有一个大小至少为2且总和为k的倍数的连续子数组,即总和为n *k 其中 n 也是一个整数。例如,如果[23, 2, 4, 6, 7]k=6,则输出应为True,因为[2, 4] 是大小为2 且总和为6 的连续子数组。

我正在尝试理解以下solution

class Solution {
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        int n = nums.size(), sum = 0, pre = 0;
        unordered_set<int> modk;
        for (int i = 0; i < n; ++i) {
            sum += nums[i];
            int mod = k == 0 ? sum : sum % k;
            if (modk.count(mod)) return true;
            modk.insert(pre);
            pre = mod;
        }
        return false;
    }
};

我了解我们正在尝试将:0, (a/k), (a+b)/k, (a+b+c)/k 等存储到 hashSet(其中 k!=0)中,并且我们在 下一个迭代中这样做,因为我们希望子数组大小至少为2

但是,这如何保证我们得到一个元素总和为k 的子数组?什么数学性质保证了这一点?

【问题讨论】:

    标签: c++ algorithm


    【解决方案1】:

    集合 modk 逐渐填充了从数组开头开始的连续子数组的所有总和(考虑为模 k)。

    关键的观察是:

    a-b = n*k 对于某些自然 n iff
    a-b ≡ 0 mod k iff
    a ≡ b 模 k

    所以如果一个连续的子数组 nums[i_0]..nums[i_1] 求和为 0 模 k,那么两个子数组 nums[0]..nums[i_0] 和 nums[i_0 + 1 ]..nums[i_1] 具有 相同的和模 k。

    因此,如果两个不同的子数组从数组的开头开始具有相同的和,以 k 为模,就足够了。

    幸运的是,这样的值只有 k 个,所以你只需要使用一组大小为 k 的值。

    一些吹毛求疵:

    • 如果 n > k,无论如何你都会有一个合适的子数组(pigeon-hole principle),所以循环实际上永远不会迭代超过 k+1 次。
    • 这里不应该涉及任何类型的类,这没有任何意义。
    • 连续,不连续。数组和子数组是离散的,不可能是连续的……

    【讨论】:

    • 对不起.. 但我的数学可能太糟糕了。当你说等式中的0 mod k 时,你的意思是k,对吧?
    • 没有。注意我使用等价符号,而不是等价
    • 来自what I understand0 modulo k = 0。那么,当您说i_0...i_1, sums up to 0 时,子数组0..i_0 and (i_0 + 1)..i_1 sum up to 的总和是0?再次抱歉! :)
    【解决方案2】:

    sum 的模基 k 等价于模基 k 的 sum 的模 k

    (a+b)%k = (a%k + b%k) %k

    (23 + 2) % 6 = 1
    ( (23%6) + (2%6) ) % 6 = (5 + 2) % 6 = 1

    modk 存储您迭代计算的所有模块。如果在迭代 i 你得到一个在 i-m 计算的重复模块,这意味着你添加了一个 m 元素的子序列,其总和是 k 的倍数

     i=0 nums[0] = 23     sum = 23    sum%6 = 5     modk = [5]
     i=1 nums[1] = 2      sum = 25    sum%6 = 1     modk = [5, 1]
     i=2 nums[2] = 4      sum = 29    sum%6 = 5     5 already exists in modk (4+2)%6 =0 
    

    【讨论】:

      猜你喜欢
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 2015-06-29
      • 2011-04-30
      • 1970-01-01
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多