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

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

本文关键字:使得 a+b%10 数组 查找      更新时间:2023-10-16

有一个有序列表,如
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,并且
  • A[i] * A[i-1]/2 如果 i = j。

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

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

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

其余的细节交给你。

希望这有帮助!

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

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;
}