Эффективный способ подсчета числа 1 в двоичном представлении числа в O (1), если у вас достаточно памяти для воспроизведения. Это вопрос интервью, который я нашел на онлайн-форуме, но у него не было ответа. Может кто-нибудь что-то предложить, я не могу подумать о способе сделать это в O (1) раз?
Количество отсчетов 1 в двоичном представлении
Ответ 1
Что проблема Хэмминга, популяция a.k.a. В ссылке упоминаются эффективные реализации. Цитирование:
С неограниченной памятью мы могли бы просто создать большую таблицу поиска веса Хэмминга каждого 64-битного целого числа
Ответ 2
У меня есть решение, которое подсчитывает бит в O(Number of 1's)
время:
bitcount(n):
count = 0
while n > 0:
count = count + 1
n = n & (n-1)
return count
В худшем случае (когда число равно 2 ^ n - 1, все 1 в двоичном виде), он будет проверять каждый бит.
Изменить: Просто нашел очень приятный постоянный алгоритм постоянной памяти для битконта. Вот он, написанный на C:
int BitCount(unsigned int u)
{
unsigned int uCount;
uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
}
Вы можете найти подтверждение его правильности здесь.
Ответ 3
Обратите внимание, что: n & (n-1) всегда исключает наименее значимые 1.
Следовательно, мы можем написать код для вычисления числа 1 следующим образом:
count=0;
while(n!=0){
n = n&(n-1);
count++;
}
cout<<"Number of 1 in n is: "<<count;
Сложность программы будет: число 1 в n (которое постоянно < 32).
Ответ 4
Я увидел следующее решение с другого сайта:
int count_one(int x){
x = (x & (0x55555555)) + ((x >> 1) & (0x55555555));
x = (x & (0x33333333)) + ((x >> 2) & (0x33333333));
x = (x & (0x0f0f0f0f)) + ((x >> 4) & (0x0f0f0f0f));
x = (x & (0x00ff00ff)) + ((x >> 8) & (0x00ff00ff));
x = (x & (0x0000ffff)) + ((x >> 16) & (0x0000ffff));
return x;
}
Ответ 5
public static void main(String[] args) {
int a = 3;
int orig = a;
int count = 0;
while(a>0)
{
a = a >> 1 << 1;
if(orig-a==1)
count++;
orig = a >> 1;
a = orig;
}
System.out.println("Number of 1s are: "+count);
}
Ответ 6
countBits(x){
y=0;
while(x){
y += x & 1 ;
x = x >> 1 ;
}
}
что это?
Ответ 7
Это будет самый короткий ответ в моей жизни SO: таблица поиска.
По-видимому, мне нужно немного пояснить: "если у вас достаточно памяти для игры", значит, у нас есть вся необходимая нам память (техническая возможность неважно). Теперь вам не нужно хранить таблицу поиска больше, чем байт или два. Хотя это технически будет Ω (log (n)), а не O (1), просто чтение числа, которое вам нужно, это Ω (log (n)), поэтому, если это проблема, тогда ответ будет невозможным, что еще короче.
Какой из двух ответов они ожидают от вас на собеседовании, никто не знает.
Есть еще один трюк: в то время как инженеры могут брать номер и говорить о Ω (log (n)), где n - это число, компьютерные ученые скажут, что на самом деле мы должны измерять время работы как функцию длины ввода, так что инженеры называют Ω (log (n)) на самом деле Ω (k), где k - количество байтов. Тем не менее, как я уже говорил, просто чтение числа равно Ω (k), поэтому мы не можем сделать это лучше.
Ответ 8
Ниже также будет работать.
nofone(int x) {
a=0;
while(x!=0) {
x>>=1;
if(x & 1)
a++;
}
return a;
}
Ответ 9
Функция принимает int
и возвращает число единиц в двоичном представлении
public static int findOnes(int number)
{
if(number < 2)
{
if(number == 1)
{
count ++;
}
else
{
return 0;
}
}
value = number % 2;
if(number != 1 && value == 1)
count ++;
number /= 2;
findOnes(number);
return count;
}
Ответ 10
Ниже приводится решение C с использованием битовых операторов:
int numberOfOneBitsInInteger(int input) {
int numOneBits = 0;
int currNum = input;
while (currNum != 0) {
if ((currNum & 1) == 1) {
numOneBits++;
}
currNum = currNum >> 1;
}
return numOneBits;
}
Ниже представлено решение Java, использующее полномочия 2:
public static int numOnesInBinary(int n) {
if (n < 0) return -1;
int j = 0;
while ( n > Math.pow(2, j)) j++;
int result = 0;
for (int i=j; i >=0; i--){
if (n >= Math.pow(2, i)) {
n = (int) (n - Math.pow(2,i));
result++;
}
}
return result;
}
Ответ 11
Есть только один способ, которым я могу придумать эту задачу в O (1)..., чтобы "обмануть" и использовать физическое устройство (с линейным или даже параллельным программированием, я думаю, что предел равен O (log ( k)), где k представляет количество байтов числа).
Однако вы можете легко представить себе физическое устройство, которое соединяет каждый бит a с выходной строкой с напряжением 0/1. Тогда вы можете просто прочитать электронное сообщение об общем напряжении на линии "суммирования" в O (1). Было бы довольно легко сделать эту основную идею более элегантной с некоторыми основными элементами схемы для вывода вывода в любой форме (например, двоичный кодированный вывод), но основная идея такая же, и электронная схема создаст правильный вывод состояние в фиксированное время.
Я предполагаю, что возможны также возможности квантовых вычислений, но если нам это разрешено, я думаю, что простая электронная схема - это более легкое решение.
Ответ 12
Я на самом деле сделал это, используя немного ловкости рук: достаточно одной таблицы поиска с 16 записями, и все, что вам нужно сделать, это разбить двоичный rep на nibbles (4-битные кортежи). Сложность на самом деле O (1), и я написал шаблон С++, который был специализирован на размер целого, который вы хотели (в # битах)... делает его постоянным выражением, а не неопределенным.
fwiw вы можете использовать тот факт, что (i и -i) возвратит вам LS однобитный и простой цикл, каждый раз отменяя lsbit, до тех пор, пока целое число не станет нулевым, но это старый трюк четности.
Ответ 13
Я пришел сюда с большим убеждением, что знаю прекрасное решение этой проблемы. Код в C:
short numberOfOnes(unsigned int d) {
short count = 0;
for (; (d != 0); d &= (d - 1))
++count;
return count;
}
Но после того, как я немного исследовал эту тему (читал другие ответы:)), я нашел еще 5 эффективных алгоритмов. Любовь SO!
Существует даже команда CPU, специально разработанная для этой задачи: popcnt
.
(упомянутый в этот ответ)
Описание и сравнительный анализ многих алгоритмов можно найти здесь.
Ответ 14
В python или любой другой конвертируйте в строку bin, затем разделите ее на "0", чтобы избавиться от 0, затем объедините и получите длину.
len(''.join(str(bin(122011)).split('0')))-1
Ответ 15
В приведенном ниже методе также можно подсчитать число 1s в отрицательных числах.
private static int countBits(int number) {
int result = 0;
while(number != 0) {
result += number & 1;
number = number >>> 1;
}
return result;
}
Однако число, подобное -1, представлено в двоичном виде как 11111111111111111111111111111111, и поэтому потребуется много сдвига. Если вы не хотите делать так много сдвигов для небольших отрицательных чисел, другой способ может быть следующим:
private static int countBits(int number) {
boolean negFlag = false;
if(number < 0) {
negFlag = true;
number = ~number;
}
int result = 0;
while(number != 0) {
result += number & 1;
number = number >> 1;
}
return negFlag? (32-result): result;
}
Ответ 16
Используя строковые операции JS, можно сделать следующее:
0b1111011.toString(2).split(/0|(?=.)/).length // returns 6
или
0b1111011.toString(2).replace("0","").length // returns 6
Ответ 17
Ниже приведены два простых примера (в С++), среди которых вы можете сделать это.
-
Мы можем просто подсчитать биты набора (1) с помощью __builtin_popcount().
int numOfOnes(int x) { return __builtin_popcount(x); }
-
Прокрутите все биты в целое число, проверьте, установлен ли бит, и если он затем увеличивает счетную переменную.
int hammingDistance(int x) { int count = 0 for(int i = 0; i < 32; i++) if(x & (1 << i)) count++; return count; }
Надеюсь, это поможет!
Ответ 18
Мне пришлось играть в гольф в рубине и в итоге
l=->x{x.to_s(2).count ?1}
Использование:
l[2**32-1] # returns 32
Очевидно, что он не эффективен, но делает трюк:)
Ответ 19
Реализация Ruby
def find_consecutive_1(n)
num = n.to_s(2)
arr = num.split("")
counter = 0
max = 0
arr.each do |x|
if x.to_i==1
counter +=1
else
max = counter if counter > max
counter = 0
end
max = counter if counter > max
end
max
end
puts find_consecutive_1(439)
Ответ 20
Два способа:
/* Method-1 */
int count1s(long num)
{
int tempCount = 0;
while(num)
{
tempCount += (num & 1); //inc, based on right most bit checked
num = num >> 1; //right shift bit by 1
}
return tempCount;
}
/* Method-2 */
int count1s_(int num)
{
int tempCount = 0;
std::string strNum = std::bitset< 16 >( num ).to_string(); // string conversion
cout << "strNum=" << strNum << endl;
for(int i=0; i<strNum.size(); i++)
{
if('1' == strNum[i])
{
tempCount++;
}
}
return tempCount;
}
/* Method-3 (algorithmically - boost string split could be used) */
1) split the binary string over '1'.
2) count = vector (containing splits) size - 1
Использование::
int count = 0;
count = count1s(0b00110011);
cout << "count(0b00110011) = " << count << endl; //4
count = count1s(0b01110110);
cout << "count(0b01110110) = " << count << endl; //5
count = count1s(0b00000000);
cout << "count(0b00000000) = " << count << endl; //0
count = count1s(0b11111111);
cout << "count(0b11111111) = " << count << endl; //8
count = count1s_(0b1100);
cout << "count(0b1100) = " << count << endl; //2
count = count1s_(0b11111111);
cout << "count(0b11111111) = " << count << endl; //8
count = count1s_(0b0);
cout << "count(0b0) = " << count << endl; //0
count = count1s_(0b1);
cout << "count(0b1) = " << count << endl; //1