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

имейте машину с памятью O(1). мы хотим пройти N номер (один за другим) в первый раз, и снова исключим два числа и передадим N-2 из них машине. напишите алгоритм, который находит недостающие числа. Это был вопрос для интервью, и я не мог его решить.

6 ответов


Это можно сделать с памятью O(1).

вам нужно всего несколько целых чисел, чтобы отслеживать некоторые текущие суммы. Целые числа не требуют логарифмических n бит (где n-количество входных целых чисел), они требуют только 2b+1 бит, где b-количество бит в отдельном входном целом числе.

при первом чтении потока добавьте все числа и все их квадраты, т. е. для каждого входного числа, n, сделайте следующее:

sum += n
sq_sum += n*n

затем на второй поток делает то же самое для двух разных значений, sum2 и sq_sum2. Теперь выполните следующие математические действия:

sum - sum2 = a + b
sq_sum - sq_sum2 = a^2 + b^2

(a + b)(a + b) = a^2 + b^2 + 2ab
(a + b)(a + b) - (a^2 + b^2) = 2ab
(sum*sum - sq_sum) = 2ab

(a - b)(a - b) = a^2 + b^2 - 2ab
               = sq_sum - (sum*sum - sq_sum) = 2sq_sum - sum*sum
sqrt(2sq_sum - sum*sum) = sqrt((a - b)(a - b)) = a - b
((a + b) - (a - b)) / 2 = b
(a + b) - b = a

вам нужно 2b+1 бит во всех промежуточных результатах, потому что вы храните продукты двух входных целых чисел и в одном случае умножаете одно из этих значений на два.


предполагая, что числа находятся в диапазоне от 1..N и 2 из них отсутствуют - x и y, вы можете сделать следующее:

используйте формулу Гаусса:sum = N(N+1)/2

sum - actual_sum = x + y

использовать произведение чисел:product = 1*2..*N = N!

product - actual_product = x * y

разрешите x, y, и у вас есть недостающие номера.

короче говоря-пройдите через массив и суммируйте каждый элемент, чтобы получить actual_sum, умножить каждый элемент, чтобы получить actual_product. Затем разрешите два уравнения для x an y.


это не может быть сделано с O(1) память.

предположим, что у вас есть константа k бит памяти, - тогда вы можете иметь 2^k возможные состояния для вашего алгоритма.

однако-вход не ограничен, и предположим, что есть (2^k) + 1 возможные ответы (2^k) + 1 различные случаи проблемы, от принцип piegeonhole, вы вернете один и тот же ответ дважды для 2 задач с разными ответами, и, таким образом, ваш алгоритм ошибочен.


вы O (1) память-что означает, что у вас есть постоянный объем памяти.

когда n номера передаются вам 1-й раз, просто держите добавляя их в одну переменную и продолжая умножать их в другой. Таким образом, в конце 1-го прохода у вас есть сумма и произведение всех чисел в 2 переменных S1 и P1. До сих пор вы использовали переменную 2 (+1, Если Вы читаете числа в памяти).

когда (n-2) цифры передаются вам во второй раз, сделайте то же самое. Храните сумму и произведение (n-2) числа в 2 других переменных S2 и P2. До сих пор вы использовали 4 переменные (+1, Если Вы читаете числа в памяти).

Если два недостающих числа x и y, потом

x + y = S1 - S2
x*y = P1/P2;

у вас есть два уравнения с двумя переменными. Решать их.

таким образом, вы использовали постоянный объем памяти (независимо от n).


void Missing(int arr[], int size)
{
  int xor = arr[0]; /* Will hold xor of all elements */
  int set_bit_no;  /* Will have only single set bit of xor */
  int i;
  int n = size - 2;
  int x = 0, y = 0;

  /* Get the xor of all elements in arr[] and {1, 2 .. n} */
  for(i = 1; i < size; i++)
    xor ^= arr[i];  
  for(i = 1; i <= n; i++)
    xor ^= i;   

  /* Get the rightmost set bit in set_bit_no */
  set_bit_no = xor & ~(xor-1);

  /* Now divide elements in two sets by comparing rightmost set
   bit of xor with bit at same position in each element. */
  for(i = 0; i < size; i++)
  {
    if(arr[i] & set_bit_no)
      x = x ^ arr[i]; /*XOR of first set in arr[] */
    else
      y = y ^ arr[i]; /*XOR of second set in arr[] */
  }
  for(i = 1; i <= n; i++)
  {
    if(i & set_bit_no)
      x = x ^ i; /*XOR of first set in arr[] and {1, 2, ...n }*/
    else
      y = y ^ i; /*XOR of second set in arr[] and {1, 2, ...n } */
  }

  printf("\n The two repeating missing elements are are %d & %d ", x, y);
}

пожалуйста, посмотрите на ссылку ниже Решение. Это объясняет метод XOR. Этот метод более эффективен, чем любой из методов, описанных выше. Это может быть то же самое, что и Виктор выше, но есть объяснение, почему это работает.

здесь