📌  相关文章
📜  数组中对(i,j)的计数,以使arr [i]是arr [j]的因数(1)

📅  最后修改于: 2023-12-03 15:26:11.119000             🧑  作者: Mango

数组中对(i,j)的计数,以使arr [i]是arr [j]的因数

这是一个非常常见的问题,即如何在给定的数组中找到所有满足条件的(i,j)对,以使arr[i]是arr[j]的因数。这个问题可以用几种算法来解决,并且有很多变化版本。在本文中,我们将详细讨论这个问题,并提供一些解决方案。

解决方案1:暴力枚举

最简单的解决方案是使用嵌套循环来枚举每一对(i,j),并检查是否满足条件。以下是简单的C++代码实现:

int countPairs(vector<int>& arr) {
    int cnt = 0;
    for(int i=0;i<arr.size();i++){
        for(int j=0;j<arr.size();j++){
            if(arr[j]%arr[i]==0 && j!=i){
                cnt++;
            }
        }
    }
    return cnt;
}

该算法的时间复杂度为 O(N^2),不适用于大规模数据集。我们需要更好的算法来解决这个问题。

解决方案2:哈希表

我们可以使用哈希表来加速查找。我们首先遍历数组,并将每个元素插入哈希表中。然后,我们再次遍历数组,并检查每个元素的其他因数是否在哈希表中。如果是,则我们将它们加入到结果中。以下是代码实现:

int countPairs(vector<int>& arr) {
    unordered_set<int> st;
    for(auto x:arr){
        st.insert(x);
    }
    int cnt = 0;
    for(int i=0;i<arr.size();i++){
        for(int j=1;j*arr[i]<=*max_element(arr.begin(),arr.end());j++){
            if(st.count(j*arr[i])>0 && j*arr[i]!=arr[i]){
                cnt++;
            }
        }
    }
    return cnt;
}

该算法的时间复杂度为 O(N*log(MAX)),其中 MAX 是数组中的最大值。

解决方案3:数学技巧

还有另一个解决方案,它利用了一些数学技巧。我们观察到,对于任何元素 x,它的因数只可能小于等于 sqrt(x)。因此,我们可以预处理每个元素的所有因数,并计算每个因数在数组中的个数。然后,我们可以在常数时间内计算出每个i的答案。以下是代码实现:

int countPairs(vector<int>& arr) {
    const int MAX = *max_element(arr.begin(),arr.end());
    vector<int> cnt(MAX+1,0);
    for(int i=0;i<arr.size();i++){
        for(int j=1;j*j<=arr[i];j++){
            if(arr[i]%j==0){
                cnt[j]++;
                if(j*j!=arr[i]){
                    cnt[arr[i]/j]++;
                }
            }
        }
    }
    int ans = 0;
    for(int i=0;i<arr.size();i++){
        ans += cnt[arr[i]]-1;
    }
    return ans/2;
}

该算法的时间复杂度为 O(N*sqrt(MAX)),可以解决大规模数据集。

总结

这个问题可以通过不同的方法来解决,包括暴力枚举、哈希表和数学技巧。我们还可以使用其他数据结构,如树和堆,来处理这个问题。选择适当的算法取决于具体情况和要求。