剑指OFFER-二进制中1的个数

剑指OFFER-二进制中1的个数

  • Question
  • Solution
    • 自身右移
    • 判断位右移
    • &运算

Question

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
关键词:二进制 位运算

Solution

自身右移

只看末尾,奇数为1偶数为0。然后整体右移一位,可以采用>>运算或者整除2。
注意:负数符号位为1,而右移是保持符号位不变,会导致所有位都为1,循环无法结束。因此先对其位与0xffffffff(Python)或者0x7fffffff(C++)保证符号位归0,并且ans初始值为1。

时间复杂度:O(N)
空间复杂度:O(1)

  • Python
class Solution:
    def NumberOf1(self, n):
        ans = 0
        if n<0:
            n &= 0xffffffff
        while(n):
            if n % 2 == 1: ## if n&1 == 1:
                ans += 1
            n //= 2 # n = n >> 1
        return ans
  • C++
class Solution {
public:
     int  NumberOf1(int n) {
         int ans = 0;
         if(n<0){
             n = n & 0x7FFFFFFF;
             ans++;
         }
         while(n){
             if(n & 1 == 1) // if(n % 2 == 1)
                 ans++;
             n = n >> 1; // n /= 2;
         };
         return ans;
     }
};

判断位右移

设置判断位从末尾依次向前。

时间复杂度:O(N)
空间复杂度:O(1)

  • Python
class Solution:
    def NumberOf1(self, n):
        ans = 0
        flag = 1
        while(n):
            if (n & flag) != 0:
                ans += 1
            flag = flag << 1;
        return ans
  • C++
class Solution {
public:
     int  NumberOf1(int n) {
         int ans = 0;
         int flag = 1;
         while(flag){
             if((n&flag) != 0)
                 ans++;
             flag = flag << 1;
         };
         return ans;
     }
};

&运算

n-1相当于对n中最末尾的1及其之后的位取反(例如1100-1= 1011),再用&运算使得保留最末尾的1之前的位数,之后全变0(1100&1011=1000,相当于保留末尾前一位,也就是第四位的1,第三位及其之后全部归0)。

时间复杂度:O(N) ~ 有多少个1循环多少次
空间复杂度:O(1)

  • Python
class Solution:
    def NumberOf1(self, n):
        ans = 0
        if n<0:
            n &= 0xffffffff #
        while n:
            ans += 1
            n &= n-1
        return ans
  • C++
class Solution {
public:
     int  NumberOf1(int n) {
         if(n<0)
             n &= 0xffffffff;
         int ans = 0;
         while(n){
             ans++;
             n &= n-1;
         }
         return ans;
     }
};

你可能感兴趣的:(二进制,位运算)