我在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 ++解决方案在减少编程时间方面非常优越,那么请提出建议。
非常感谢。
答案 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方法。应该足够有效率。