剑指offer-JZ11

二进制中1的个数

https://www.nowcoder.com/practice/8ee967e43c2c4ec193b040ea7fbb10b8?tpId=13&tqId=11164&rp=1&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking&tab=answerKey

c++
首先将10进制转换为2进制,然后统计其中1的个数。
这里需要注意一些特殊形式的数,因此考查了进制转换、以及正负数二进制存储的一些标准。
因此最直接思路如下:

class Solution {
public:
     int  NumberOf1(int n) {
         int ans=0;
         while ( n!=0){
             int tmp = n%2;
             if(tmp ==1)ans++;
             n=n/2;
         }
         return ans;
     }
};

但是针对有一些特殊情况无法判断:
32位二进制 能够表示
图片说明
源码:
图片说明
补码:
按照这个计算思路:

class Solution {
public:
     int  NumberOf1(int n) {
         vector<int> bin(32,0);
         if (n<0) bin[31]=1;
         int index=0;
         while(n != 0){
             if (n%2) bin[index]=1;
             index++;
             n = n/2;
         }
         if (bin[31]==1){
             for(int i=0; i<31; i++){
                 bin[i]=!bin[i];
             }
             index =0;
             bin[index]++;
             while(bin[index] == 2){
                 bin[index]=0;
                 index++;
                 bin[index]++;
             }
             bin[31]=1;
         }
         int ans=0;
         for(int i=0; i<=31; i++){
             if(bin[i] == 1) ans++;
         }
         if (bin[31]==1 && ans==1){
             return 1;
         }else{
             return ans;
         }
     }
};

PS: 其中正数区域可以计算,负数求余需要+1, 最小的数求余要+1
二进制存储: 反码的补码。
先计算源码-----取反-------+1

利用移位直接操作:

class Solution {
public:
     int  NumberOf1(int n) {
         int mask =0x01;
         int ans=0;
         while(mask !=0){
             if(mask & n) ++ans;
             mask<<=1;
         }
         return ans;
     }
};

另外一种思路,利用二进制一个特性:如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作,计算个数,但是效率比较低。

class Solution {
public:
     int  NumberOf1(int n) {
         int ans=0;
         while(n!=0){
             ans++;
             n=n&(n-1);
         }
         return ans;
     }
};
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务