面试题 10

1 题目描述

计算数的二进制表示中的 1 的个数,例如把 9 表示成二进制是 1001,有 2 位是1.


2 解决方法

第一种方法:依次右移 n ,检查最右边一位是不是 1

int numberOf1(int n){
    int count=0;
    while(n){
        if(n&1){
            count++;
        }
        n=n>>1;
    }
    return count;
}

存在问题,对于负数,此方法将导致无限循环,因为负数右移会在最左边用符号位 1 补齐,所以 n 永远不会等于 0,此方法不可行。

第二种方法,不移动 n,而是每次将 flag 左移一位,直到 flag 为 0 为止

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

此方法可以实现,循环的次数等于整数二进制的位数,32 位的整数需要循环32次。

第三种方法:对于任意一个二进制形式的数存在以下规律

   10001000 - 1 = 1000 0 111

假设一个二进制数最右边第一个 1 位于第 m 位,那么减去 1 时, m 位变为 0 ,m 位左边不变,右边全部变为 1。此时我们将减 1 之后的数与原整数进行按位与运算,结果成功将第 m 位的 1 变成了 0。

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

二进制数中有多少个 1,方法将循环多少次,直到去掉所有的 1 ,使得原整数等于 0 。


3 其他应用

把一个整数减去 1 之后再和原来的整数作为运算,得到的结果相当于是把整数的二进制表示中的最右边一个 1 变成 0 。

应用 1 :用一条语句判断一个整数是不是为 2 的整数次方。如果一个数是 2 的整数次方那么那么它的二进制表示中有且只有一位是 1 。

void if2Power(int n){
   if(n-1&n){
        printf("\n%d 不是 2 的整数次方",n);
   }else{
        printf("\n%d 是 2 的整数次方",n);
   }
}

应用 2 :计算需要改变 m 的二进制表示中的多少位才能得到 n 。比如 10 的二进制表示为 1010 ,13 的二进制表示为 1101 需要改变 1010 中的 3 位 才能得到 1101。m ^ n 然后计算异或结果中 1 的个数。

int findDif(int m,int n){
    int temp=m^n;
    return numberOf1_2(temp);
}

全部代码

#include<stdio.h>
int numberOf1(int n){
    int count=0;
    while(n){
        if(n&1){
            count++;
        }
        n=n>>1;
    }
    return count;
}  //此方法不可行
int numberOf1_1(int n){
    int flag=1;
    int count=0;
    while(flag){
        if(n&flag){
            count++;
        }
        flag=flag<<1;
    }
    return count;
} //此方法可行,循环 32 次

int numberOf1_2(int n){
    int count=0;
    while(n){
        count++;
        n=n&n-1;
    }
    return count;
}   //此方法可行,循环次数为原整数二进制表示中 1 的个数
//用一条语句判断一个整数是不是为 2 的整数次方
void if2Power(int n){
   if(n-1&n){
        printf("\n%d 不是 2 的整数次方",n);
   }else{
        printf("\n%d 是 2 的整数次方",n);
   }
}

//计算需要改变 m 的二进制表示中的多少位才能得到 n 。
int findDif(int m,int n){
    int temp=m^n;
    return numberOf1_2(temp);
}
//测试用例
void main(){
    printf("%d",numberOf1(1));
    printf("\n");
    printf("%d",numberOf1_1(-1));
    printf("\n");
    printf("%d",numberOf1_2(-1));
    if2Power(10);
    if2Power(16);
    printf("\n");
    printf("%d",findDif(10,13));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值