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;
}
运行结果
具体实现(法二)
** 关键点**
按位与运算符“&”是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位都为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;
}
运行结果
复杂度
- 时间复杂度 O(n) --- n为二进制数的位数,需要遍历一次
- 空间复杂度 O(1) --- 常数级变量,没有额外的辅助空间
小结
今天题目没有消化好,后续必须得再回顾