在位数组中找到缺少的数字

时间:2014-09-09 03:13:03

标签: algorithm

这个问题直接来自Cracking the Coding Interview, 4th Ed,所以我不是百分百肯定我可以在这里发布;如果没有,请告诉我,我会删除它。

问题5.7

  

数组A [1..n]包含从0到n的所有整数,除了一个   丢失的号码。在这个问题上,我们无法访问整个   A中的整数,只有一个操作。 A的元素是   以二进制表示,是我们可以用来访问的唯一操作   它们是“获取A [i]的第j位”,这需要恒定的时间。写   用于查找缺少的整数的代码。你能在O(n)时间内完成吗?

我知道如何解决这个问题。我不明白的是如何解决它。她的方法:

  1. 从最少的sig开始。
  2. 计算1和0的发生次数。
  3. 如果count(1)< count(0)=>丢失的数字有一个1,因为它是最小的sig位,否则它有一个0。
  4. 删除所有数字,其中sig位与步骤3中找到的结果不匹配。
  5. 重复步骤1-> 4,从最小sig位迭代 - >第二个sig位 - > ... - >大多数sig位
  6. n 的形式为(2 ^ m)-1 时,对于某些正 m ...我可以看到这种情况有效但是看不出它在一般情况下会如何起作用。

    考虑二进制基数中的自然数。然后第i个最小sig位的序列如下:

    1. 0,1,0,1,0,1,0,... = {01} * = {(1)0(1)1} *
    2. 0,0,1,1,0,0,1,1,... = {0011} * = {(2)0(2)1} *
    3. 0,0,0,1,1,1,0,0,0,... = {000111} * = {(3)0(3)1} *
    4. 然后,对于某些 s ,大多数sig位具有一些序列{(s)0(s)1}。如果 n =(2 ^ m)-1 ,那么一切都很好;对于每个量级,#1s =#0,因此我们可以使用作者逻辑。 但是,这在一般情况下如何运作?如果 n 是某个任意数字,则导致 n 的大多数sig位的序列如下所示:(s)0(s)1(s)0(s) 1 ...(k)1(显然序列必须以1作为大多数sig位结束), k 可以是[0,s]中的任何数字。那么她的逻辑如何应用? (最值得注意的是,第3步假设#0在通常情况下最多比#1更多1)

      谢谢,如果有人能对此有所了解!谢谢!

3 个答案:

答案 0 :(得分:9)

有三种可能性:

  1. n是奇数,因此0位和1位的数量应该相同。它们不会,所以较低的数字显然是缺失的数字。
  2. n是偶数,因此0位的数量应该比1位的数量大1。如果它们相等,那就是缺少0位。
  3. 如上所述,n是偶数。如果0位的数量比1位的数量大2,则1位是缺失的位。
  4. 通过删除已删除的所有数字,您现在再次以递归方式应用完全相同的问题。

答案 1 :(得分:1)

我作为作业遇到了这个问题。尽管我知道讲师可能正在寻找更高级的东西,但我认为最简单的方法仍然可以在这里使用:即使您只能一点一点地访问整数,也可以在O(n) time中计算其总和。准确地说,只需阅读32 * n bits并进行数学计算即可。然后将您与n*(n+1)/2进行比较,然后您就会知道答案。

我想在这里提及的一件事是

这实际上不是O(n)算法,否则称为线性算法。它实际上是一个伪线性,因为您需要n * W运算,其中W是所有整数的平均长度(除非问题明确指出,否则不要总是假设它们具有32位)。 W独立于n,因此不能完全证明它是线性算法。

答案 2 :(得分:-1)

更改前面提到的xor解决方案。 bit0 = XOR所有数字的bit0都是0到N的所有bit0的数组和XOR simillarly找到bit1到bit31。 然后结果是 bit0 | (bit1<< 1)...(bit31<< 31) 我已经编写了一个数字测试代码,可以使用最多3位写入。期待我的工作。此代码可以扩展为32位int。 如果这种方法有任何错误,请告诉我。感谢Poul在早期的解决中发现错误。

#include <stdio.h>

int main()
{

    unsigned int a[7] = {0,6,2,3,4,5,1};
    unsigned int bit0, bit1, bit2, missing,i;
    bit0 = getbit(a[0], 0);
    bit1 = getbit(a[0], 1);
    bit2 = getbit(a[0], 2);
    for (i=1 ; i <sizeof(a)/sizeof(unsigned int); i++)
     {
          bit0 ^= getbit(a[i],0) ;
          bit1 ^= getbit(a[i],1);
          bit2 ^= getbit(a[i],2);
     }
     for(i = 0; i <= sizeof(a)/sizeof(unsigned int); i++)
     {
          bit0 ^= getbit(i,0);
          bit1 ^= getbit(i,1);
          bit2 ^= getbit(i,2); 
     }

     missing  = bit0 | (bit1<<1) | bit2 << 2;
     printf("%u\n",missing);
    return 0;
}
int getbit(unsigned int x, unsigned int pos)
{
   return ( (x & (1 << pos)) >> pos) ;
}