Найти два недостающих числа
имейте машину с памятью 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. Этот метод более эффективен, чем любой из методов, описанных выше. Это может быть то же самое, что и Виктор выше, но есть объяснение, почему это работает.