Подсчитайте пары чисел с равным числом единиц в их двоичном представлении

#python #list #algorithm #bit-manipulation

Вопрос:

Учитывая массив положительных целых чисел a, ваша задача состоит в том, чтобы подсчитать количество пар i и j (где 0 ≤ i < j < a.length ), таких что a[i] и a[j] имеют одинаковое количество 1 в их двоичных представлениях.

размер ограничения(a)

Пример

 input=[3,4,5,6,1,2]

ans=6

possible pairs=[(3,5)(3,6)(5,6)(4,1)(4,2)(1,2)]
 

Мой Сол:

 def numPairs(input):
    count=0
    for i in range(0,len(input)):
        for j in range(i 1,len(input)):
            if bin(input[i]).count('1')==bin(input[j]).count('1'):
                count =1
    return count
 

Это решение дает ошибку ограничения по времени

Можем ли мы преобразовать это решение в 1 цикл, как две суммы?

Ответ №1:

 from collections import Counter

def num_pairs(input_arr): 
    res = 0 
    counter = Counter() 
    for el in input_arr: 
        num_ones = bin(el).count("1") 
        res  = counter[num_ones] 
        counter[num_ones]  = 1 
    return res
 

Это решение выполняется во O(n) времени и O(log n) пространстве, если мы рассмотрим операцию подсчета единиц в каждой числовой константе. В противном случае мы можем сказать, что он выполняется O(n log n) вовремя, так как нам нужны log n операции для подсчета количества единиц в каждом числе.

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

Ваше текущее решение имеет квадратичную временную сложность. Вы все еще можете выполнить небольшую оптимизацию, сохранив количество единиц input[i] при сравнении со всеми следующими input[j] .

Ответ №2:

функция bin() возвращает двоичную строку с заданным числом. подсчитайте(«1»), чтобы получить число 1 в двоичном представлении, и из этого списка найдите количество комбинаций.

Вот решение

 def numPairs(inputs):
    sum=0
    L = list(map(lambda x: bin(x).count("1"), inputs))
    for i in range(max(L) 1):
        c=L.count(i)
        if c>1:
            sum  = c*(c-1)/2
    return int(sum)
 

Или может сойти с ума еще больше и принять одностороннее решение. Это так же эффективно, как и для чистого решения python. особенно с точки зрения пространства, поскольку он не создает список. временная сложность будет равна O(n).

 from collections import Counter
from functools import reduce

def numPairs(inputs):
    return int(reduce(lambda x,y: x y, map(lambda x: x*(x-1)/2, Counter(map(lambda x: bin(x).count("1"), inputs)).values())))

print(numPairs([3,4,5,6,1,2])) # prints 6