У вас есть 2
дела здесь:
Вырожденный случай: N == 1
, что очевидно. 0 -> 1
и 1 -> 0
; Вы можете, скажем, поставить его как ~item
Общая информация Дело N > 1
. Все, что вам нужно сделать, это xor все значения:
101 ^ 110 ^ 100 ^ 000 ^ 111 ^ 011 ^ 010 == 001
алгоритм имеет O(N * 2**N)
сложность по времени (мы должны прочитать каждую ячейку матрицы) и требует O(n)
места (для хранения временной суммы при хоринге).
C # реализация ( Linq ):
string source = "3 101 110 100 000 111 011 010";
// "001"
// new char[] { ' ', '\r', '\n', 't' } - to be on the safe side -
// whatever delimiter is we'll get a correct array
string result = source
.Split(new char[] { ' ', '\r', '\n', 't' }, StringSplitOptions.RemoveEmptyEntries)
.Skip(1) // we don't want "3"
.Aggregate((sum, item) => // xoring strings
string.Concat(sum.Zip(item, (x, y) => (char)((x - '0') ^ (y - '0') + '0'))));
Давайте докажем правильность алгоритма (N > 1
).
Так как N > 1
и, следовательно, 2**N >= 4
, тогда 2**(N - 1)
- это некоторое четное значение . Давайте посмотрим на произвольный бит всех 2**N
элементов серии power
000...0...0
000...0...1
...
111.......0
111...1...1
^
- N/2 '0's (even) and N/2 '1' (even), xor == 0
мы находим, что у нас есть ровно N / 2
ноля и N / 2
единицы; xor всех этих битов равно 0
(поскольку N / 2 == 2**(N - 1)
является некоторым четным значением).
Если пропущена одна строка, например 0...1...1
у нас есть 2
возможностей:
- Пропущенный бит -
1
. Итак, у нас есть N / 2
нолей и N / 2 - 1
единиц; xor всех битов возвращает 1
- Пропущенный бит равен
0
. Итак, у нас есть N / 2 - 1
нуля и N / 2 - 1
единицы; xor всех битов возвращает 1
Поскольку ^
является побитовой операцией (значение j
-го бита не зависит от значений i
-го бита), и мы доказываем, что произвольный бит является правильным во всем значении тоже правильно.