如何在C++中找到重复元素的索引?

How to find duplicate elements' index in C++?

本文关键字:元素 索引 C++      更新时间:2023-10-16

在c++中是否有任何STL函数允许我在数组中找到重复项的所有索引?

例如

:

int array[] = {1,1,2,3,4};

应该返回0,1

可以有效地使用std::unordered_set(唯一地跟踪重复索引)和std::unordered_map(跟踪唯一的数字及其索引)。

这是在O(N * [O(1) + ... + O(1)]) …近似= O(N):

template<typename ForwardIterator>
std::vector<int> get_duplicate_indices(ForwardIterator first, ForwardIterator last){
    std::unordered_set<int> rtn;
    std::unordered_map<int, int> dup;
    for(std::size_t i = 0; first != last; ++i, ++first){
        auto iter_pair = dup.insert(std::make_pair(*first, i));
        if(!iter_pair.second){
            rtn.insert(iter_pair.first->second);
            rtn.insert(i);
        }
    }
    return {rtn.begin(), rtn.end()};
}

解释:

给定一个数组A

  • 使用一组唯一索引,rtn .
  • Using a KV (Key-Value) map, dup;其中k为数组A中的一个元素,v为该元素在数组中的索引。

  • 对于数组中索引为ia项:

    • 查找kv,如果a作为k存在于dup
    • 如果存在,
      • i插入rtn
      • v插入rtn
    • Else,将ai作为kv加入dup
  • 返回rtn

查看完整示例:Live on Coliru.


对于输入:

int array[] = {1,1,2,3,4};

我们的输出是:

1 0

,

对于输入:

int array[] = {1, 1, 2, 3, 4, 1, 0, 0, 9};

我们的输出是:

7 0 5 1 6

如果需要按顺序排列索引,可以简单地对结果数组进行排序。

我不认为有一种开箱即用的STL方法可以做到这一点。这是一个O(N*N)的解决方案:

    int array[] = {1, 2, 3, 1, 4};
    constexpr int size = 5; // ToDo - don't hardcode this.
    bool duplicates[size] = {};
    for (std::size_t i = 0; i < size; ++i){
        if (!duplicates[i]){ /*No point in re-testing*/
            for (std::size_t j = i + 1; j < size; ++j){
                if (array[i] == array[j]){
                    duplicates[i] = duplicates[j] = true;
                }
            }
        }
    }

基于排序的方法对于较长的数组可能更有效,但是您必须构建一个新位置->旧位置的表来获取重复元素的索引。

我个人的看法。虽然不太确定这个大O(我看起来像O(N)):

std::vector<std::size_t> findDuplicateIndices(std::vector<int> const & v)
{
    std::vector<std::size_t> indices;
    std::map<int, std::pair<int, std::size_t>> counts; // pair<amount, firstSeenPos>
    for (std::size_t i = 0 ; i < v.size() ; ++i)
    {
        std::size_t const amount = ++counts[v[i]].first;
        /**/ if (amount == 1) // First encounter, record the position
        {
            counts[v[i]].second = i;
            continue;
        }
        else if (amount == 2) // Second encounter, add the first encountered position
            indices.push_back(counts[v[i]].second);
        indices.push_back(i);
    }
    return indices;
}

上网试试!