Найти недостающее число в массиве бит

Эта проблема берется непосредственно из Cracking the Coding Interview, 4th Ed, поэтому я не уверен, что могу опубликовать ее здесь на 100%; если нет, просто дайте мне знать, и я удалю это.

Вопрос 5.7:

Массив A [1..n] содержит все целые числа от 0 до n, за исключением одного номер которого отсутствует. В этой проблеме мы не можем получить доступ ко всему целое число в с одной операцией. Элементы A являются представленный в двоичном формате, и единственная операция, которую мы можем использовать для доступа они "извлекают j-й бит A [i]", который занимает постоянное время. Написать кода, чтобы найти недостающее целое число. Можете ли вы сделать это в O (n) времени?

Я знаю, как это решить. Я не понимаю, как она это решила. Ее метод:

  • Начните с младшего бита sig.
  • Нахождение счетчика 1 против 0.
  • Если count (1) < count (0) = > недостающее число имеет 1 как минимальный бит sig, иначе у него есть 0.
  • Удалите все числа с наименьшим битом sig, не соответствующим результату, найденному на шаге 3.
  • Повторите шаги 1- > 4, итерация с младшего бита sig → 2-й младший бит sig → ... → самый старший бит

Я вижу, что это работает, когда n имеет вид (2 ^ m) -1 для некоторого положительного m... но не видит, как он будет работать в общем случае.

Рассмотрим натуральные числа в двоичном базисе. Тогда последовательность бит ith-little sig будет выглядеть так:

  • 0,1,0,1,0,1,0,... = {01} * = {(1) 0 (1) 1} *
  • 0,0,1,1,0,0,1,1,... = {0011} * = {(2) 0 (2) 1} *
  • 0,0,0,1,1,1,0,0,0,... = {000111} * = {(3) 0 (3) 1} *

Тогда самый старший бит имеет некоторую последовательность {(s) 0 (s) 1} для некоторого s. Если n = (2 ^ m) -1, то все хорошо; для каждой величины, # 1s = # 0 и, следовательно, мы можем использовать логику авторов. Но как это работает в общем случае? Если n - некоторое произвольное число, последовательность битов большинства sig, ведущих к n, выглядит так: (s) 0 (s) 1 (s) 0 (s) 1... (k) 1 (очевидно, последовательность должна заканчиваться с 1 как самый бит sig), а k может быть любым числом в [0, s]. Итак, как ее логика применяется? (В частности, шаг 3 предполагает, что # 0 не более 1 больше, чем # 1 в обычном случае)

Спасибо, если кто-нибудь может пролить свет на это! Спасибо!

Ответ 1

Есть 3 возможности:

  • n нечетно, поэтому число бит 0 и бит 1 должны быть одинаковыми. Их не будет, поэтому меньшее число, очевидно, является недостающим.
  • n четный, поэтому число бит 0 должно быть на 1 больше, чем количество бит 1. Если они равны, то бит 0 отсутствует.
  • Как и выше, n является четным. Если число бит 0 на 2 больше числа бит 1, бит 1 является отсутствующим.

Удалив все числа, которые были устранены, вы снова применяете ту же проблему снова, рекурсивно.

Ответ 2

Изменение ранее упомянутого решения xor. bit0 = XOR: все бит 0 из присутствующих чисел - это массив и XOR всех бит 0 от 0 до N simillarly найти бит1 в бит31. Тогда результат бит0 | (бит1 < 1)... (бит31 < 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) ;
}