C:检测长数组中的重复整数

时间:2013-06-04 13:12:49

标签: c sorting optimization duplicates

我在SO和其他地方看过各种类似的问题,但我觉得有一些特殊情况可能需要一个新问题。

这就是问题:

我有一个整数数组,其中可以有高达10亿的整数。这些数字将在1到10亿之间,但可能缺少值。所以每个值32位就足够了。我唯一想做的就是确保没有重复。当我发现重复的第一次出现时,我大惊小怪并退出。这是在许多文件上完成的,文件很少有重复的文件。所以平均情况也常常是最坏的情况。

我知道如何在shell中很容易地做到这一点(在文本文件中我将从整数中读取:sort | uniq等)并且它需要大约13秒。所以,希望纯粹的C智能算法会做得更好。我的想法是我在数组上使用快速(希望随时可用)排序并迭代计算每个连续对的差异。我找到零的那一刻我停下来退出。

这是一个玩具示例:

1001
1002
1003
1004
1005
1003
...

我首先对数组进行排序并得到:     1001     1002     1003     1003     1004     1005     ...

然后当我看到第3行 - 第4行== 0时,我停在第4行。

如果一切顺利,那么我会以退出代码零静默退出。

这些是我的要求/限制: 1)我是C的初学者(我的腰带只有几百行代码)。 2)我非常喜欢纯C解决方案来学习。标准库是可以的。 3)如果C ++解决方案在减少编程时间方面非常优越,那么请提出建议。

非常感谢。

3 个答案:

答案 0 :(得分:2)

这是哈希解决方案的快速伪代码,因此您可以获得它背后的“概念”。我会尝试将其设为C,但不要认为它已经过编译和测试。但它会很接近。

#include <iostream>
using namespace std;

const int NUM_BITS = 32;

bool noDuplicates(const int INPUT[], const int SIZE, const int MIN_VALUE, const int MAX_VALUE) {

    const unsigned int RANGE = (MAX_VALUE - MIN_VALUE) / NUM_BITS;  //Use unsigned int, can support wider ranges this way.

    int isPresent[RANGE];// Might need dynamic allocation here, don't know if C supports this type of array initialization

    for(int i = 0; i < RANGE; i++) isPresent[i] = 0;//Probably don't need this loop on most systems.  Aslo, there are faster ways to zero memory.

    for(int i = 0; i < SIZE; i++) {

        const int ADJUST_TO_ZERO = INPUT[i] - MIN_VALUE; //adjust our min value to zero index now every possible value should map to an indice in our "isPresent" array
        const int INT_IN_ARRAY = ADJUST_TO_ZERO / NUM_BITS; // Each int represents 32 values, or our bit is hiding in the (VALUE/32)th slot
        const unsigned int BIT_VALUE = 1 << (ADJUST_TO_ZERO % NUM_BITS); // This is identical to 2 ^ (ADJUST_TO_ZERO % NUM_BITS)

        cout << "CHECKING: " << ADJUST_TO_ZERO << " ARRAY INDEX: " << INT_IN_ARRAY << " BIT:" << (ADJUST_TO_ZERO % NUM_BITS) << " INT REPRESENTATION: " << BIT_VALUE << endl;

        if(isPresent[INT_IN_ARRAY] & BIT_VALUE) { //bitwise &, with a value 2 ^ BIT, isolates this "BIT"
            return false;
        }

        isPresent[ADJUST_TO_ZERO / NUM_BITS] += BIT_VALUE; //If we add 2^BIT to an int, we are only adding the value to this to set this "BIT"
    }
    return true; //If we escape the loop above there are no duplicates
}


int main() {
    const int SIZE = 65;
    int array[SIZE];

    for(int i = 0; i < SIZE; i++) {
        array[i] = i;
    }

    array[SIZE - 1] = 30;

    cout << "RESULT: " << noDuplicates(array, SIZE, 0, 100) << endl;
}

答案 1 :(得分:1)

你没有说你的值的范围是什么,但是假设它是32位整数的范围,位图数组将是512MB,这适用于大多数现代机器而没有太多麻烦。尝试这样的事情:

/* Assumes 32-bit ints */
int verify_unique( <data source> ) {
    unsigned int *bitmap = calloc(128 * 1024 * 1024, 4);
    if (!bitmap) { <error> }

    while ( <more input> ) {
        unsigned int value = <next value>;
        unsigned int index = value >> 5;
        unsigned int mask = 1 << (value & 0x1f);

        if (bitmap[index] & mask) {
            <found duplicate>
            break;
        }
        bitmap[index] |= mask;
    }
    free(bitmap);
}

答案 2 :(得分:0)

尝试counting sort对数组进行排序,然后执行link3减去link4方法。应该足够有效率。