(没有懂)【蓝蓝计算机考研算法】-day22-计算二进制数中1的个数

135 阅读2分钟

31、输入一个整数n,输出该数32位二进制表示中1的个数。其中负数用补码表示。

数据范围:-2^31 <= n<=2^31-1
即范围为:-2147483648 <= n <= 2137483647

示例

输入: 10
返回值: 2

说明:

十进制中10的32位二进制表示为 0000 0000 0000 0000 0000 0000 0000 1010,其中有两个1。

思路

法一:将得到的数字分别与1按位与运算,将得到的结果放入字符数组中,然后再将字符数组进行遍历,如果为1,则count累加,遍历完成后输出即可。

法二:遍历整数n二进制的每一位,如果为 1 则计数器加1,最后返回计数器。其中通过移位运算实现遍历每一位,通过按位与运算确定该位是否为1。 具体做法:

  • 遍历二进制的32位,通过向左移位运算。
  • 将移位后的1与数字n进行按位与运算,结果不为0,计数器就加1。

具体实现(法一)

#include <stdio.h>
#include <stdlib.h>

char *toBinary(int num)
{
    char *binary = (char *)malloc(sizeof(char) * 33);
    int flag = 1;
    int i;

    for (i = 31; i >= 0; i--)
    {
        if (num & flag)
        {
            binary[i] = '1';
        }
        else
        {
            binary[i] = '0';
        }
        flag << 1;
    }
    binary[32] = '\0';

    return binary;
}

int main()
{
	int n,count = 0;
    char *tmp;
    
    scanf("%d", &n); 
    tmp = toBinary(n);
    for(int i = 0;i < 32;i++) {
    	if(tmp[i] == '1')
    		count++;
	}
    free(tmp);
    tmp = NULL;
    printf("%d", count);

    return 0;
}

运行结果

image.png

具体实现(法二)

** 关键点**

  • 按位与运算符“&”是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位都为1时,结果位才为1。参与运算的两个数均以补码出现。(知识点✅)

  • 思路一中如何确定该位是否为1的,因为数字1的二进制除最低为1外,其余位都为0,当它与数字n进行按位与运算后,当前位若为1的话,最后结果只有最后1位为1,其余全为0,否则全为0。

#include <iostream>
using namespace std;

int NumberOf1(int n) {
    int num = 0;                          //计数器
    for (int i = 0; i < 32; i++) {
        if ((n & (1 << i)) != 0) num++;  //判断是否为1
    }
    return num;  // 返回结果
}

int main() {
    int res = NumberOf1(10);//测试数据
    cout << "其中1的个数为:" << res;
}

运行结果

image.png

复杂度

  • 时间复杂度 O(n) --- n为二进制数的位数,需要遍历一次
  • 空间复杂度 O(1) --- 常数级变量,没有额外的辅助空间

小结

今天题目没有消化好,后续必须得再回顾