leetCode 191. Number of 1 Bits

本文介绍了LeetCode 191题目的四种解法,包括使用测试位、直接右移、除法取余及消除最低位1的方法。通过对这些方法的分析和对比,得出在不同情况下选择合适算法的重要性。

    题目链接:https://leetcode.com/problems/number-of-1-bits/

    题目内容:

Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also known as the Hamming weight).

For example, the 32-bit integer ’11' has binary representation 00000000000000000000000000001011, so the function should return 3.

    题目分析:

    这道题我选择当一回《编程之美》的搬运工,在“求二进制数中1的个数”这一节有详细的说明。

    1> 首先是我自己的一种解法,定义一个uint_t的变量作为测试位,初始化为1,即00000000000000000000000000000001,用移位的方式测试给定数的每一位,并加到计数器中。其中要取得给定数n在某一位上的数字,还需要将测试位和n的“与操作”的结果做一个移位,所以的数目为迭代的次数。具体如代码所示

class Solution {
public:
    int hammingWeight(uint32_t n) {
    	int count = 0;
    	uint32_t test = 1;
    	for(int i=0;i<32;i++) {
    	    count += (n&test) >> i;
    	    test <<= 1;
    	}
    	return count;
    }
};

    2> 上述运行的结果是8ms,但是其实没什么必要定义一个测试位,只要每次让给定数n右移,并与0x01做“与操作”就能得到每一位上的数字,这就是《编程之美》上面的解法二,测试了下,的确要快了一些,用了4ms,至少在这道题上是这样。

int count = 0;
for (int i = 0; i < 32; i++) {
    count += n&0x01;
    n >>= 1;
   }
return count;
    3> 下面祭出编美里的第一种解法,其实也是最容易想到的,编美上第一种解法往往不是最好的,从分析来看的确是这样,通过除法和取余的操作肯定比位运行慢,因为bit才是计算机最喜欢的语言。原理是这样的,每次对n取余,这样的结果肯定就是最后一位的数字,用计数器加起来,这样之后将n除以2,表示往右移了一位。比较打脸的是,该解法的在这道题的运行速度上也是4ms。

int count = 0;
    while(n) {
        if(n % 2 == 1)
    	    count++;
    	n /= 2;
    }
    	return count;

    4> 按照编美上面的解释,也的确有道理,有些零的位没必要做测试或者累加操作,只计算当前的某一个1就行了,直接贴出解法。

int count = 0;
    while(n) {
    	count++;
    	n &= (n-1);
    }
return count;


    又一次打脸的是,这个解法也是用了8ms。。。当然,编美上面还有传统的暴力打表法,向来是oj中最为不耻但是效率最好的,毕竟下标O(1)啊。

    补充一下:在这道题中已经指明了是unsigned int,因此是不用考虑负数的。假设输入的参数中规定是整数,即n可能为负数,这时候解法2就失效了,因为对于带符号的整数右移,如果整数n是正数,右移的时候会在最左也就是最高位补0,这没问题;如果n是负数,为了保证右移后还是负数,右移的时候会在最左也就是最高位补1,这样最后整个数变成0XFFFF而导致死循环,因此要根据输入的类型选择算法,按照编美和剑指offer的推荐首选解法4.

### LeetCode Problems Involving Counting the Number of 1s in Binary Representation #### Problem Description from LeetCode 191. Number of 1 Bits A task involves writing a function that receives an unsigned integer and returns the quantity of '1' bits within its binary form. The focus lies on identifying and tallying these specific bit values present in any given input number[^1]. ```python class Solution: def hammingWeight(self, n: int) -> int: count = 0 while n: count += n & 1 n >>= 1 return count ``` This Python code snippet demonstrates how to implement the solution using bitwise operations. #### Problem Description from LeetCode 338. Counting Bits Another related challenge requires generating an output list where each element represents the amount of set bits ('1') found in the binary notation for integers ranging from `0` up to a specified value `n`. This problem emphasizes creating an efficient algorithm capable of handling ranges efficiently[^4]. ```python def countBits(num): result = [0] * (num + 1) for i in range(1, num + 1): result[i] = result[i >> 1] + (i & 1) return result ``` Here, dynamic programming principles are applied alongside bitwise shifts (`>>`) and AND (`&`) operators to optimize performance during computation. #### Explanation Using Brian Kernighan Algorithm For optimizing further especially with large inputs, applying algorithms like **Brian Kernighan** offers significant advantages due to reduced iterations needed per operation compared against straightforward methods iterating through all possible positions or dividing repeatedly until reaching zero. The core idea behind this method relies upon subtracting powers-of-two corresponding only to those places holding actual ‘ones’ thereby skipping over zeroes entirely thus reducing unnecessary checks: ```python def hammingWeight(n): count = 0 while n != 0: n &= (n - 1) count += 1 return count ``` --related questions-- 1. How does the Hamming weight calculation differ between signed versus unsigned integers? 2. Can you explain why shifting right works effectively when determining counts of one-bits? 3. What optimizations exist beyond basic iteration techniques for calculating bit counts? 4. Is there any difference in implementation logic required across various programming languages supporting similar syntaxes? 5. Why might someone choose the Brian Kernighan approach over other strategies?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值