【问题标题】:Optimal Algorithm needed for finding pairs divisible by a given integer k寻找可被给定整数 k 整除的对所需的最佳算法
【发布时间】:2016-04-07 01:12:45
【问题描述】:

给定n个整数和一个整数k,告诉给定n个整数有多少对这样的整数对,使得对中两个元素的和可以被k整除?

我不知道 n 和 k 的界限。因此,为简单起见,假设 n 和 k 不是很大。

不用说,尽可能给出最优解。 (我知道天真的方法:-)! )

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    两个数之和是否能被k整除仅取决于它们的余数模k

    因此,如果k 相当小,您可以计算每个可能的余数有多少个数,并从中计算对数。假设k > 0 和所有整数都是非负数

    unsigned long long combinations(unsigned k, unsigned long long *arr, unsigned n) {
        unsigned long long counts[k] = {0};
        unsigned i;
        for(i = 0; i < n; ++i) {
            ++counts[arr[i]%k];
        }
        // number of pairs where both are divisible by k
        unsigned long long combs = counts[0]*(counts[0]-1)/2;
        for(i = 1; i < (k+1)/2; ++i) {
            combs += counts[i]*counts[k-i];
        }
        if (k == 2*i) {
            combs += counts[i]*(counts[i] - 1)/2;
        }
        return combs;
    }
    

    O(n+k) 的步骤完成工作。如果n 很小而k 很大,则朴素算法更好。

    【讨论】:

    • 你打败了我 :) 但是,你想在你做梳子的地方使用 counts[],而不是 arr[],你需要考虑 counts[0]
    • 太棒了!线性时间..这就是我要找的..谢谢!
    • @rici 感谢您的提醒。 counts[0] 用于combs 的初始化,我没有忘记这一点(但我还有一个错字,k-1 而不是k-i)。
    【解决方案2】:

    除了Daniel Fischer所说的,如果k非常大,可以将数字mod k排序,然后将排序后的列表从两端(处理完0 mod k值后)向中间(k/ 2 模 k)。那是 O(n log n),比 O(n^2) 更好,假设你的幼稚算法真的很幼稚。

    【讨论】:

    • 我的天真涉及二进制搜索...所以这也是 O(n log n) 但是是的,您的版本是一个改进...因为它只涉及 O(n log n) 进行排序.. 并且使用二分搜索在线性 O(n) 时间而不是 O(n log n) 时间内进行查找。谢谢 ! +1 :)
    • 你可以使用哈希表而不是排序/二进制搜索来降低到 O(n)。
    • @KeithRandall,是的,你可以试试。我希望我的解决方案通常会更快,因为它的内部循环非常快,但我很可能是错的。如果您想尝试一下,我建议整数 mod k 的良好散列将是整数 mod k mod p,其中 p 是接近 n 的素数。这将存储保持在 O(n),这与搜索和扫描相比具有竞争力。 (使用整数 mod k 本身当然可以保证没有冲突,但是您已经将问题简化为 Daniel 的 binsort,在这种情况下我们已经丢弃了它,因为 bin 占用了太多内存。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    • 2012-07-26
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多