逐位计算1个数

  • 有两种思路,一种右移n,每次与1进行与运算;另一种是左移1,每次与n进行与运算,由于n为负数时右移会填充1,所以选择左移1的思路
    public class Solution {
      public int NumberOf1(int n) {
          int ans = 0;
          int mark = 1;
          while(mark != 0) {
              // 判断某位是否为1
              if((mark & n) != 0) {
                  ans++;
              }
              // 左移一位
              mark <<= 1;
          }
          return ans;
      }
    }

逐步消1,计算次数

  • 对于任意一个正整数n,n&(n-1)由于(n-1)向最低1位借位的关系会消去最低1位,所以进行多少次n&(n-1)操作就是含多少个1
  • 对于任意一个负整数n:

    有:n的补码 + -n的补码(正整数) = 0的补码((溢出1)0...0)
    则:n的补码 = 0的补码((溢出1)0...0) - -n的补码(正整数)
    则:n的补码 = 的原码(10...0) - -n的原码(正整数)
    则:n的补码 = ( + n)的原码(正整数)

以上,可以得知对负数n补码的处理就是对( + n)的原码(正整数)的处理,所以+1-1的操作可以直接作用于补码,即n&(n-1)也会由于(n-1)向最低1位借位的关系会消去最低1位,所以进行多少次n&(n-1)操作就是含多少个1

public class Solution {
    public int NumberOf1(int n) {
        int ans = 0;
        // 每次消去一个1
        while(n != 0) {
            n &= n - 1;
            ans++;
        }
        return ans;
    }
}