二进制中1的个数

来源:互联网 发布:ubuntu无法登录界面 编辑:程序博客网 时间:2024/06/05 00:00

题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
时间限制:1秒 空间限制:32768K

知识点
位运算

思路
1、先判断整数二进制表示中最右边一位是不是1。接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断是不是1。这样每次移动一位直到整个整数变成0 为止。现在的问题变成怎么判断一个整数的最右边是不是1了。这很简单,只要把整数和1做位与运算看结果是不是0就知道了。1除了最右边的一位之外所有位都是0。1除了最右边的一位之外所有位都为0。如果一个整数与1做与运算的结果是1,表示该整数最右边一位位是1,否则是0。(剑指Offer)
问题:如果是负数,则会陷入死循环。

代码:
语言:Java 运行时间: 1001 ms 占用内存:0K 状态:运行超时

public class Solution {    public int NumberOf1(int n) {        int count = 0;        while(n != 0){            if((n & 1) == 1)                count ++;            n = n >> 1;        }        return count;    }}

2、为了避免死循环,我们可以不右移输入的数字i。首先把i和1做与运算,判断i的最低位是不是1.接着把1左移一位得到2,再和i做与运算,就能判断i的次低位是不是1……这样反复左移,每次都能判断i的其中一位是不是1.
这种解法中循环的次数等于整数二进制的位数,32位的整数需要循环32次。
代码:
语言:Java 运行时间: 15 ms 占用内存:8528K 状态:答案正确

public class Solution {    public int NumberOf1(int n) {        int count = 0;        int flag = 1;        while(flag != 0){            if((n & flag) != 0)                count ++;            flag = flag << 1;        }        return count;    }}

3、优解(几个1循环几次):
把一个整数减去1,都是把最右边的1变成00.如果它的右边还有0的话,所有的0都变成1,而它左边所有位都保持不变。接下来我们把一个整数和它减去1的结果做位与运算,相当于把它最右边的1变成0.还是以前边的1100为例,它减去1的结果是1011。我们再把1100和1011做位与运算,得到的结果是1000。我们把1100最右边的1变成了0,结果刚好就是1000.
总结一下:把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。
代码:
语言:Java 运行时间: 13 ms 占用内存:8272K 状态:答案正确

public class Solution {    public int NumberOf1(int n) {        int count = 0;        while(n != 0){            count ++;            n = n & (n - 1);        }        return count;    }}
原创粉丝点击