在没有排序的情况下搜索数组中重复项的最快方法是什么?

时间:2014-03-08 11:10:01

标签: c++ c arrays

我有一个数组1 2 2 3 4.我希望在索引之后找到一个元素的重复数。所以前两个重复的数量是1,第二个重复的数量是0.我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:3)

将您看到的元素放入基于散列的地图中。

从集合的后面开始,向后移动,并将项添加到哈希映射中。如果您要添加的元素不存在,请将其重复计数设置为零,并将1放入该元素的地图中。如果计数已经存在,那么它的重复计数就是地图中的任何数量。将该数字存储为重复计数,并增加地图中的值。

vector<int> data({1, 2, 2, 3, 4});
unordered_map<int,int> count;
vector<int> res(data.size(), 0);
for (int i = data.size()-1 ; i >= 0 ; i--) {
    res[i] = count[data[i]]++;
}
for (int i = 0 ; i != res.size() ; i++) {
    cout << data[i] << " - " << res[i] << endl;
}

Demo on ideone.

答案 1 :(得分:0)

如果n是数组的大小而i是元素的索引,则每个元素都需要扫描 n - i - 1 元素。结果你将进行 n *(n - 1)元素的比较。

您可以使用标准算法std::count

例如

const size_t N = 5;

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

for ( int *first = a; first != a + N; ++first )
{
   std::cout << *first << '\t' << std::count( first, a + N, *first ) - 1 << std::endl;
} 

或者

for ( int *first = a; first != a + N; ++first )
{
   std::cout << *first << '\t' << std::count( first + 1, a + N, *first ) << std::endl;
} 

同样可以写成

for ( auto *first = std::begin( a ); first != std::end( a ); ++first )
{
   std::cout << *first << '\t' << std::count( first, std::end( a ), *first ) - 1 << std::endl;
} 

for ( auto *first = std::begin( a ); first != std::end( a ); ++first )
{
   std::cout << *first << '\t' << std::count( std::next( first ), std::end( a ), *first ) << std::endl;
} 

答案 2 :(得分:0)

不知道这是否是最快的方法,但我的提议是:

  • 创建具有相同数量元素的辅助数组,并使用0 s
  • 进行初始化
  • 检查最后一个元素的重复项;
    • 使用1
    • 标记上次复制的第二个
    • 然后是2
    • 的第三个
    • 等......
  • 检查从最后到第一个元素的重复项,如果元素具有0以外的重复标记,则跳过

在C中这样:

#include <stdio.h>
#define Length 10

int main( ) {

    int SomeNumbers[Length] = { 1, 2, 2, 3, 4, 5, 20, 9, 2, 3 };
    int DupCount[Length] = { 0 };

    for ( int i = Length - 1; i >= 0; i-- ) {
        if ( DupCount[i] == 0 ) {
            int dup = 0;
            for ( int j = i - 1; j >= 0; j-- )
                if ( SomeNumbers[i] == SomeNumbers[j] )
                    DupCount[j] = ++dup;
        }
    }

    for ( int i = 0; i < Length; i++ ) printf( "%d ", DupCount[i] );

    getchar( );
    return 0;

}

答案 3 :(得分:0)

就速度而言,最有效的方法通常是使用频率表。通常,它是将值映射到其出现次数的结构。在这种情况下,您可以映射到索引的列表/数组(即值发生的每个位置的索引)。

算法将遍历每个元素,并将其添加到表中。如果找到重复项,则会在地图中的该位置附加索引列表/数组。

如果您需要知道有多少重复项,例如数字2,然后在表中查找其条目。存储在那里的索引数是重复的总数。要查找给定值的实例后重复项的数量,只需检查所需索引后出现的索引数。