Как поменять местами единицы и нули в двоичном представлении числа без перебора значений?

я пробовал подобный код:

s = '01110'
s2 = ''
for i in s: # перебор всех значений
    if i == '1':
        s2 += '0'
    else:
        s2 += '1'
print(s)

но так как подобный код будет работать достаточно долго на подобных строках с большей длинной, данный способ не подходит


Ответы (2 шт):

Автор решения: MaxU

Вариант решения без цикла:

res = bin(2**len(s) - 1 - int(s, 2))[2:]

Простой и быстрый вариант решения, используя работу со строками:

res = s.replace("1", "2").replace("0", "1").replace("2", "0")
→ Ссылка
Автор решения: CrazyElf

Вообще есть нативные питоновские функции для таких преобразований строк:

t = str.maketrans('01', '10')
print('01110'.translate(t))

Вывод:

10001

maketrans просто создаёт словарь, переводящий соответствующие символы одной строки в символы другой строки, там по сути коды символов внутри. Вот что находится в t:

{48: 49, 49: 48}

48 - это код символа 0, а 49 - код символа 1.

Работает это в общем-то довольно быстро:

%%time
s = '01110' * 100_000
s1 = s.translate(t)

Вывод:

CPU times: user 1.08 ms, sys: 0 ns, total: 1.08 ms
Wall time: 1.09 ms

Хотя оба варианта от MaxU на той же строке работают в 100 раз быстрее, если что, порядка 8 µs.

P.S. Ваш код работает долго из-за того, что вы плюсуете строки на каждом шагу цикла, при этом каждый раз создаётся новая строка всё большей длины. Такого метода однозначно нужно избегать в первую очередь.

→ Ссылка