📌  相关文章
📜  从具有相等和和商的数组中计算对(1)

📅  最后修改于: 2023-12-03 14:49:21.573000             🧑  作者: Mango

从具有相等和和商的数组中计算对

有一个长度为 $n$ 的整数数组 $a[]$,满足该数组中任意两个元素 $a[i]$ 和 $a[j]$($i\ne j$)的和相等,且 $a[i]$ 与 $a[j]$ 的商相等。请你计算该数组中所有符合条件的数对 $(i,j)$ 的数量。

简单思路

我们可以先遍历数组 $a$,对于每个元素 $a[i]$,我们可以进行一次线性搜索,寻找数组中所有与 $a[i]$ 的和相等且和 $a[i]$ 的商相等的元素 $a[j]$。这样一来,我们就可以得到所有符合条件的数对 $(i,j)$。由于我们需要进行两次遍历,该算法的时间复杂度为 $O(n^2)$。

进一步优化

如果我们能够在一次遍历中找到所有符合条件的数对 $(i,j)$,那么我们的算法的时间复杂度就可以是线性的。假设 $r$ 是所有不同的商的数量,我们可以对数组 $a$ 进行一次排序,并将数组 $a$ 中的元素按照商的值进行分组。然后,对于每个分组中的元素 $a[i]$,我们需要寻找其他分组中所有与 $a[i]$ 相加为 $a[i]\times k$ 的元素,其中 $k$ 是 $a[i]$ 与其他元素之间的商。

这一算法的核心在于如何快速查找数组中某个元素。常用的查找算法有很多,如二分查找、哈希表等。对于本题而言,我们可以使用哈希表(或者 C++ 中的 unordered_map)来加速查找。

时间复杂度为 $O(n\log n)$(排序)或 $O(n)$(哈希表),空间复杂度为 $O(n)$。

代码示例
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n);

    // 输入数组
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }

    // 将数组排序
    sort(a.begin(), a.end());
    // 分组
    unordered_map<int, vector<int>> groups;
    for (int i = 0; i < n; ++i) {
        groups[a[i]].push_back(i);
    }

    int cnt = 0;
    // 遍历数组,并在哈希表中查询符合条件的数对
    for (int i = 0; i < n; ++i) {
        for (int j : groups[a[i]]) {
            if (j > i) {
                cnt += groups.count(a[j]-a[i]) && find(groups[a[j]-a[i]].begin(), groups[a[j]-a[i]].end(), j) == groups[a[j]-a[i]].end();
            }
        }
    }

    cout << cnt << endl;
    return 0;
}
参考链接