繁体   English   中英

给定一个大小为 N 的数组 a[],其中包含从 0 到 N-1 的元素,您需要找到在给定数组中出现不止一次的所有元素

[英]Given an array a[] of size N which contains elements from 0 to N-1, you need to find all the elements occurring more than once in the given array

给定一个大小为 N 的数组 a[],其中包含从 0 到 N-1 的元素,您需要找到在给定数组中出现不止一次的所有元素。 输入:N = 4 a[] = {0,3,1,2} Output: -1 解释:N=4 并且从 0 到 (N-1 = 3) 的所有元素都存在于给定数组中。 因此 output 为 -1。

以下解决方案有什么问题?

vector<int> duplicates(int arr[], int n) {
        unordered_set<int> m;
        vector<int> ans;
        for(int i=0;i<n;i++){
            //if element is found
            if(m.find(arr[i])!=m.end())
                ans.push_back(arr[i]);
            //if element is not found
            else
                m.insert(arr[i]);
    }
    if(ans.empty())
        ans.push_back(-1);
    return ans;
}

如果值出现两次以上,此解决方案会多次返回值。

例如,对于a = {1, 1, 1} 1} ,当正确答案仅为{1}时,它将返回{1, 1} } 。

解决方案有一个问题。 对于集合中已有的每个值,您将把该值添加到结果中。 如果有超过 2 个相同的值,那么您将始终将相同的值再次添加到结果向量中。

让我们看下面的例子: {1,2,3,42,42,42,42}

Loop 
run   value  set         vector
 0      1     1            -
 1      2     1,2          -
 2      3     1,2,3        -
 3      42    1,2,3,42     -
 4      42    1,2,3,42     42         Duplicate found. Add to vector   
 5      42    1,2,3,42     42,42      Again duplicate found. Add again to vector 
 6      42    1,2,3,42     42,42,42   Again duplicate found. Add again to vector 

因此,不幸的是,此解决方案将行不通。

相反,您需要做的是查明某个值是否多次出现。 这可以通过计算值然后检查,如果计数大于 1,然后将值添加到生成的std::vector

计数的标准方法是使用std::unordered_map ,我们可以在其中将计数与每个值相关联。

因此,首先我们将计算所有值。 然后,如果计数大于 1,我们将评估计数器并将所有值添加到结果向量中。

一个潜在的解决方案可能是这样的:

#include <iostream>
#include <vector>
#include <unordered_map>

std::vector<int> duplicates(int arr[], int n) {

    // Here we will count the occurence of each integer in the array
    std::unordered_map<int, unsigned int> counter{};

    // Do the counting
    for (int i = 0; i < n; ++i)
        counter[arr[i]]++;
    
    // This will hold the result. Either the duplicates, or -1 of no duplicate
    std::vector<int> result{};

    // Check all counted values. If the counter is more than one for a vakue, add it (only one time to the result)
    for (const auto& [value, count] : counter)
        if (count > 1) result.push_back(value);

    // If there was no duplicate, then add -1 to the vector
    if (result.empty()) result.push_back(-1);

    return result;
}
int main() {
    int arr[]{ 0,1,2,3,42,42,42};
    for (int i : duplicates(arr, sizeof(arr) / sizeof(arr[0])))
        std::cout << i << ' ';
}

我将展示带有评论的原始解决方案。 通过阅读评论,您将了解问题所在。

我建议你尽可能多地写评论。 然后,您将在早期阶段自行检测问题。

#include <vector>
#include <iostream>
#include <unordered_set>

using namespace std;

vector<int> duplicates(int arr[], int n) {

    // This set can contain only unique values
    unordered_set<int> m;

    // Here we will store the result
    vector<int> ans;

    // Iterate over all values in the array
    for (int i = 0; i < n; i++) {

        // Check, if the value from the array is already in the set
        if (m.find(arr[i]) != m.end())

            // Yes it is alread in the set
            // So add it to the resulting answer
            // **** But caveat: If there are 5 identical duplicates, 
            // we will add 4 times the value to the answer --> Bug
            ans.push_back(arr[i]);
        else
            // If element is not found, so, was not yet present in the set, add it
            m.insert(arr[i]);
    }
    // Special case for no duplicates
    if (ans.empty())
        ans.push_back(-1);
    return ans;
}
int main() {
    int arr[]  {0,1,2,3,42,42,42,42,42};
    for (int i : duplicates(arr, sizeof(arr)/sizeof(arr[0])))
        cout << i << ' ';
}

Gassa 正确识别了一个错误。 解决方法是在两次迭代中执行此操作,而不是尝试在数组的一次迭代中执行此操作。

这是一个不用set的简单方法。 通过使用另一个向量,利用数组中所有元素都在 0..N-1 之间的事实。

vector<int> duplicates(int arr[], int n) {

    vector<int> table;     // tracks number of occurrences of a value in arr
    vector<int> duplicates;

    table.resize(n);
    for (int i = 0; i < n; i++)
    {
       table[arr[i]]++;
    }

    for (int i = 0; i < n; i++)
    {
       if (table[i] > 1)
       {
          duplicates.push_back(i);
       }
    }
    if (duplicates.size() == 0)
    {
       duplicates.push_back(-1);
    }
    return duplicates;
}

您只能一次性完成。

std::vector<int> dups(int arr[], int n)noexcept {
    int i;
    std::vector<int> lut(n), ret;
    for (i = 0; i != n; ++i) {
        if (++lut[arr[i]] == 2) {
            ret.emplace_back(arr[i]);
        }
    }
    if (ret.empty()) {
        ret.emplace_back(-1);
    }
    return ret;
}

lut[elem] 给出了 arr 中 elem 可用的次数。 要成为重复元素,必须在 arr 中多次可用。 你只关心第二次。 第二次在 arr 中找到 elem 时,将其存储在 ret 中。

暂无
暂无

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

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