leetCode 191. Number of 1 Bits
2016-01-29 20:00
567 查看
题目链接: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
so the function should return 3.
题目分析:
这道题我选择当一回《编程之美》的搬运工,在“求二进制数中1的个数”这一节有详细的说明。
1> 首先是我自己的一种解法,定义一个uint_t的变量作为测试位,初始化为1,即00000000000000000000000000000001,用移位的方式测试给定数的每一位,并加到计数器中。其中要取得给定数n在某一位上的数字,还需要将测试位和n的“与操作”的结果做一个移位,所以的数目为迭代的次数。具体如代码所示
2> 上述运行的结果是8ms,但是其实没什么必要定义一个测试位,只要每次让给定数n右移,并与0x01做“与操作”就能得到每一位上的数字,这就是《编程之美》上面的解法二,测试了下,的确要快了一些,用了4ms,至少在这道题上是这样。
4> 按照编美上面的解释,也的确有道理,有些零的位没必要做测试或者累加操作,只计算当前的某一个1就行了,直接贴出解法。
又一次打脸的是,这个解法也是用了8ms。。。当然,编美上面还有传统的暴力打表法,向来是oj中最为不耻但是效率最好的,毕竟下标O(1)啊。
补充一下:在这道题中已经指明了是unsigned int,因此是不用考虑负数的。假设输入的参数中规定是整数,即n可能为负数,这时候解法2就失效了,因为对于带符号的整数右移,如果整数n是正数,右移的时候会在最左也就是最高位补0,这没问题;如果n是负数,为了保证右移后还是负数,右移的时候会在最左也就是最高位补1,这样最后整个数变成0XFFFF而导致死循环,因此要根据输入的类型选择算法,按照编美和剑指offer的推荐首选解法4.
题目内容:
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.
相关文章推荐
- MLlearning(1)——kNN算法
- DDAL技术方案选型
- Android必学-异步加载(三阶段:优化ListView加载可见项)
- css切图Sprites
- 用 Python 做数据处理必看:12 个使效率倍增的 Pandas 技巧(上)
- xcode代码上传到Github上
- text-overflow
- 为什么空循环进程会导致CPU占有率很高?
- The Java™ Tutorials — Generics :Wildcard Capture and Helper Methods 通配符匹配和辅助方法
- JVM的GC简介和实例
- 体绘制之光线投射算法(附源码)
- 第一章链表
- C++ 知识点
- 单例模式
- undefined reference to `sin'问题解决
- unknown software exception
- Html书签的使用
- mcm C 数据抓取
- ARP原理及双网卡设备arp、ping查询问题
- Fragment处理与Activity状态丢失(State Loss)