剑指offer之二进制中1的个数

简介: 剑指offer之二进制中1的个数

1 问题

实现一个函数,输入一个函数,输出该二进制数据中1的个数。例如9表示二进制数据1001,有2位是1,因此输入9,该函数会输出2。


2 分析

我们先了解下计算机里面位运算,有5种


1)& 这个是与操作,规律如下

1 & 1 = 1     1 & 0 = 0     0 & 1= 0    0 & 0 = 0


2)| 这个是或运算,规律如下

1 | 1 = 1     1 | 0 = 1     0 | 1= 1    0 | 0 = 0


3)^ 异或运算,规律如下

1 ^ 1 = 0     1 ^ 0 = 1      0 ^ 1 = 1     0 ^ 0 = 0


4) 左移 m<<n 表示把m左移n位,在左移n位的时候,最左边的n位丢弃,同时右边补上n个0 比如

00001010 << 2 = 00101000

10001010 << 3 = 01010000


5) 右移 左移 m >> n 表示把m右移n位,在右移n位的时候,最右边补上n个0 ,最左边分2种情况,如果数字是一个无符号整形

则用0填补最左边的n位,如果是一个有符号的数据,则最左边用数字的符号填补n个数据。如果是正数,左边补n个0,是负数左边补n个1.

00001010 >> 2 = 00000010


10001010 >> 3 = 11110001


这里我们可以把原数据和1进行&操作,如果二进制数据尾巴进行&操作,如果包含1的话&1操作就是1,返之结果为0,然后我们把数据进行右移一位就行。

如果一个正数要除以2,我们效率最高的是把这个数据进行右移一位。


3 代码实现

C++版本

#include <stdio.h>
/*
 *二进制数据里面包含数字1的个数
 */
int containOneNumber(int value)
{
    int count = 0;
    while (value != 0)
    {
        //这里是(value & 1)不是(value  & 0)
        if (value & 1)
            ++count;
        //这里是value = value >> 1,而不是value >> 1; 我们要用变量接收它
        //不然不管就只执行了一次也就是value除以了2,所以导致死循环。
        value = value >> 1;
    }
    return count;
}
int main(void) 
{
    int result = containOneNumber(9);
    printf("result is %d\n", result);
    return 0;
}

java版本

public int containOneNumber(int value)
    {
        int count = 0;
        while (value != 0)
        {
            if ((value & 1) != 0)
            {
                count++;
            }
            value = value >>> 1; //>>>就是java中的无符号右移
        }
        return count;
    }

我们知道java用 >>> 是无符号右移,右移的时候,所以最高位左边都是0,如果这个数是负数的时候,右移的话最高位会补1,

C++版本就会变成死循环。


4 优化

方法1:

n与1做与运算,判断n的最低位是不是为1,接着把1左移一位得到2,再和n做与运算,就能判断n的次低位是不是1….这样反复左移

int containOneNumber1(int n)
{
    int flag = 1;
    int count = 0;
    while (flag != 0)
    {
        if ((flag & n) != 0)
        {
            count++;
        }
        flag = flag << 1;
    }
    return count;
}

方法2:

把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0,那么一个整数的二进制表示中有
多少个1,就可以进行多少次这样的操作

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

5 总结

1) 把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0,那么一个整数的二进制表示中有多少个1


2)n与1做与运算,判断n的最低位是不是为1,接着把1左移一位得到2,再和n做与运算,就能判断n的次低位是不是1….这样反复左移


3) 如果是正整数的情况下,我们可以把正整数右移动和1进行&操作,然后再去统计。


相关文章
|
1月前
《剑指offer》——二进制中1的个数
《剑指offer》——二进制中1的个数
【剑指offer】-二进制中1的个数-11/67
【剑指offer】-二进制中1的个数-11/67
|
4月前
|
存储 Java
剑指Offer LeetCode 面试题15. 二进制中1的个数
剑指Offer LeetCode 面试题15. 二进制中1的个数
28 0
|
10月前
|
机器学习/深度学习 C++
剑指offer 14. 二进制中1的个数
剑指offer 14. 二进制中1的个数
33 0
|
10月前
剑指Offer - 面试题15:二进制中1的个数
剑指Offer - 面试题15:二进制中1的个数
48 0
|
10月前
剑指offer_位运算---二进制中1的个数
剑指offer_位运算---二进制中1的个数
34 0
|
10月前
|
算法 C语言
编程之美求二进制数中1的个数
编程之美求二进制数中1的个数
67 0
|
11月前
「题解」解决二进制数中1的个数
🐰取余取模法 🐰按位与法 🐰n=n&(n-1)法 🐰随记
【剑指offer】二进制中1的个数&&2的幂
【剑指offer】二进制中1的个数&&2的幂
【剑指offer】二进制中1的个数&&2的幂
LeetCode 1290. 二进制链表转整数
给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。
81 0