繁体   English   中英

在数组中查找对,使得 a+b%10 = k

[英]Find pairs in an array such that a+b%10 = k

有一个有序列表,如
A=[7, 9, 10, 11, 12, 13, 20]
我必须找到对 a+b%10=k 其中 0<=k<=9

例如 k = 0
对:(7, 13), (9, 11), (10, 20)

如何在 O(n) 时间内找到对

我试图用 take mod(10) 找到转换所有列表

for (auto i : A) {

    if (i <= k) {
        B.push_back(i);
    }
    else {
        B.push_back(i % 10);
    }       
}

之后,我尝试定义通过 unorderep_map 给出 k 的总和

unordered_map<int, int> sumList;
int j = k;
for (int i = 0; i < 10; i++) {
    sumList[i] = j;
    if (j==0) j=9;
    j--;
}

但是我不知道如何计算 O(n) 中的对数,我现在该怎么办?

让我们从一个简单的例子开始。 假设 k = 0。这意味着我们想要找到总和为 10 的倍数的对数。这些对会是什么样子? 好吧,它们可以由

  • 将最后一位数字为 1 的数字与最后一位数字为 9 的数字相加,
  • 将一个最后一位为 2 的数与一个最后一位为 8 的数相加,
  • 将最后一位为 3 的数与最后一位为 7 的数相加,
  • 将最后一位数字为 4 的数字与最后一位数字为 6 的数字相加,或
  • 将两个最后一位为 5 的数字相加,或
  • 将最后一位为 0 的两个数相加。

因此,假设您有一个频率表 A,其中 A[i] 是最后一位为 i 的数字的数量。 那么末位分别为 i 和 j 的数字对的数量由下式给出

  • A[i] * A[j] 如果 i ≠ j,并且
  • 如果 i = j,则 A[i] * A[i-1] / 2。

基于此,如果您想计算总和为 k mod 10 的对数,您可以

  • 填充A数组,然后
  • 迭代所有可能的对,总和为 k,使用上面的公式计算对的数量,而不明确列出所有对。

最后一步需要时间 O(1),因为只有 10 个存储桶,并且迭代您需要的对,因此最多需要恒定的工作量。

我将把细节的rest留给你。

希望这可以帮助!

您可以为此修改计数排序。 以下是未经测试、未经优化且仅用于说明的版本:

int mods[10];

void count_mods(int nums[], int n) {
        for (int i = 0; i < n; i++)
                mods[nums[i]%10]++;
}

int count_pairs(int k) {
        // TODO: there's definitely a better way to do this, but it's O(1) anyway..
        int count = 0;
        for (int i = 0; i < 10; i++)
                for (int j = i+1; j < n; j++)
                        if ((i + j) % 10 == k) {
                                int pairs = mods[i] > mods[j] ? mods[j] : mods[i];
                                if (i == j)
                                         pairs /= 2;
                                count += pairs;
                        }

        return count;
}

编辑:使用较小的常数。

int mods[10];

void count_mods(int nums[], int n) {
        for (int i = 0; i < n; i++)
                mods[nums[i]%10]++;
}

int count_pairs(int k) {
        int count = 0;
        for (int i = 0; i < 10; i++) {
                int j = k - i;
                if (j < 0)
                        j += 10;
                count += min(mods[i], mods[j]);
                // When k = 2*i we count half (rounded down) the items to make the pairs.
                // Thus, we substract the extra elements by rounding up the half.
                if (i == j)
                        count -= (mods[i]+1) / 2;
        }
        // We counted everything twice.
        return count / 2;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM