我有一个大小为“n”的数组,在[0-99]之间有未分类和重新整数的整数。我已经知道有一个号码遗失了。那么,找到丢失号码的最快方法是什么? 这是我迄今为止在C中的解决方案。
int find_missing_number(int array[], int n)
{
char checker[100] = {0};
int xor = 0, counter = 0, i, temp;
//xor = (n%4==0) ? 0 : (n%4==1) ? n-1 : (n%4==2) ? 1 : n;
for(i = 0; i < n; i++)
if(checker[temp = array[i]] == 0)
{
checker[temp] = 1;
xor ^= temp;
if(++counter == 99)
return xor;
}
return -1;
}
答案 0 :(得分:1)
由于有重复的元素,在编写我之前的解决方案之前我没想到,我相信解决方案的复杂性是最好的。
我建议,您可以只读取检查器数组,而不是xor'ing元素,以找到缺少的元素。
int find_missing_number(int array[], int n)
{
int checker[100] = {0};
for(int i = 0; i < n; i++)
checker[array[i]]++;
for(int i=0; i <100; i++)
if(0 == checker[i])
return i;
}
这将减少取决于n的操作,使代码更快,更大的n。
答案 1 :(得分:1)
您可以在O(n)中执行此操作。迭代数组并计算所有数字的总和。现在,从1到N的自然数之和可以表示为Nx(N + 1)/ 2。在你的情况下N = 99。从Nx(N + 1)/ 2中减去数组的总和,其中N = 99。 这是缺少的数字。在迭代期间可以检测空槽,其中计算总和。
我不完全确定这是否是一种更快的方法,但你可以选择尝试。
编辑:如果您没有重复的值,这将有效。
答案 2 :(得分:1)
鉴于您可能有重复项,我没有看到任何方法可以保留某些记录,显示您可以按每个值读取哪些值。基于一种或另一种单向散列函数(其中两种被提出然后被撤回)的方法不能自己完成这项工作。但是,通过将其与类似哈希的函数组合在一起,可以节省扫描所见值的记录的工作量。例如,
int find_missing_number(int array[], int n)
{
char checker[100] = {0};
int xor = XOR_OF_1_TO_100;
int i;
for(i = 0; i < n; i++) {
xor ^= (checker[array[i]] ? 0 : array[i] + 1);
checker[array[i]] = 1;
}
return xor - 1;
}
这无疑与您的版本非常相似,但我更有信心它会起作用,而且我认为它的运行速度可能会稍快。
请注意,我没有声明任何变量register
- 编译器比我选择哪些变量应该存在于寄存器中要好得多,哪些不是,并且没有义务就此问题采纳我的建议无论如何。
此外,checker
数组的元素具有类型char
,允许一次存放在CPU缓存行中的数量是它们类型int
的四倍(假设为1) -byte char
和4字节int
s。。
另请注意,我避免计算不同的值或以其他方式在循环内分支(三元表达式可以在没有分支的情况下实现)。避免计数和条件语句将加速确实缺少一个值的情况,并且实际上可能会或可能不会减慢没有丢失的情况。增益可能来自于不仅仅是拥有更少的代码 - 有时这种简化也可以让编译器生成更有效的指令序列。
当然,如果可能缺少一个以上的值,那么整个事情就是垃圾(问题没有明确说明)。
答案 3 :(得分:1)
原始程序已经很快了。但是,鉴于问题陈述,可以通过更改它来加快速度:
if(++counter == 100)
return -1;
到此:
if(++counter == 99)
return xor;
此更改会导致程序在找到99个不同的元素时立即返回答案。因此,如果数组非常大,则只处理数组的一小部分,并且可以忽略数组的其余部分。这取决于问题陈述,该陈述声明已知缺少一个元素。
答案 4 :(得分:1)
Javia1492在他的回答中有一个主要想法:总结数字。
checker
数组会阻止您将两次相同的数字相加。
counter
变量计算结束搜索的不同数字的数量,然后在您已经有99个不同的值时测试数组中的整个n
数字。
它也可以像你一样使用xor运算符,但我不太喜欢它,因为1 ^ 2 ^ 3 ^ .. ^ 99 == 0是某种特殊情况你可以&#39; t用1 ^ 2 ^ .. ^ N。
进行推广int find_missing_number(int array[], int n)
{
char checker[100];
register int sum = 0, counter = 0, i, temp;
memset(checker, 0, sizeof(checker));
for (i = 0; i < n; i++)
{
if (checker[temp = array[i]] == 0)
{
checker[temp] = 1;
sum += temp;
if (++counter == 99)
break;
}
}
return 4950 - sum; // (100*99)/2 - sum
}