剑指Offer 面试题15. 二进制中1的个数(Java代码)

前往LeetCode做题

题目描述

给定一个 int型的数字,求它的二进制表示有多少个1.

题解

涉及到了二进制,就应该使用位运算了。

x & (x-1) 可以消除最低位的二进制位1

代码

public class Solution {
    public int NumberOf1(int n) {
        int count = 0;
        while(n != 0){
	        // 去除最低位的 1        
            n = (n&(n-1));
            count++;
        }
        return count;
    }
}

错误典型

以下一些方式是错误的:

  • 认为有特殊情况,int值为Integer.MIN_VALUE,决定使用long类型来承接int值
    	public class Solution {
        public int NumberOf1(int n) {
            long b = n;
            int count = 0;
            // 去除最低位的 1
            while(b != 0){
                b = (b&(b-1));
                count++;
            }
            return count;
        }
    }
    
    Integer.MIN_VALUE在两种类型中的表现形式是不一样的
    int型:10000000000000000000000000000000
    long型:1111111111111111111111111111111110000000000000000000000000000000
    
  • 使用位运算移位的方式,让字符串右移动
    public class Solution {
        // you need to treat n as an unsigned value
        public int hammingWeight(int n) {
            int count = 0;
            while(n != 0){
                if((n & 1) == 1) count++;
                // 这里使用符号错了
                n = n >> 1;
            }
            return count;
        }
    }
    
    这里属于不熟悉位运算的移位操作,>>表示的移位,我们一般的理解是类似于 /2 操作。这种移位是保留符号的,我们以为的Integer.MIN_VALUE >移位:
    10000000000000000000000000000000
    1000000000000000000000000000000
    100000000000000000000000000000
    10000000000000000000000000000
    1000000000000000000000000000
    100000000000000000000000000
    10000000000000000000000000
    1000000000000000000000000
    100000000000000000000000
    10000000000000000000000
    1000000000000000000000
    100000000000000000000
    10000000000000000000
    1000000000000000000
    100000000000000000
    10000000000000000
    1000000000000000
    100000000000000
    10000000000000
    1000000000000
    100000000000
    10000000000
    1000000000
    100000000
    10000000
    1000000
    100000
    10000
    1000
    100
    10
    1
    
    实际上的Integer.MIN_VALUE >>移位:
    10000000000000000000000000000000
    11000000000000000000000000000000
    11100000000000000000000000000000
    11110000000000000000000000000000
    11111000000000000000000000000000
    11111100000000000000000000000000
    11111110000000000000000000000000
    11111111000000000000000000000000
    11111111100000000000000000000000
    11111111110000000000000000000000
    11111111111000000000000000000000
    11111111111100000000000000000000
    11111111111110000000000000000000
    11111111111111000000000000000000
    11111111111111100000000000000000
    11111111111111110000000000000000
    11111111111111111000000000000000
    11111111111111111100000000000000
    11111111111111111110000000000000
    11111111111111111111000000000000
    11111111111111111111100000000000
    11111111111111111111110000000000
    11111111111111111111111000000000
    11111111111111111111111100000000
    11111111111111111111111110000000
    11111111111111111111111111000000
    11111111111111111111111111100000
    11111111111111111111111111110000
    11111111111111111111111111111000
    11111111111111111111111111111100
    11111111111111111111111111111110
    11111111111111111111111111111111
    11111111111111111111111111111111
    11111111111111111111111111111111
    ... 陷入死循环
    
    明确一点:
    • >>是有符号右移,相等于 /2,负数的那最高位 1是不会移动的
    • >>>是无符号位移,是可以将最高位的 1移动的
    public class Solution {
        // you need to treat n as an unsigned value
        public int hammingWeight(int n) {
            int count = 0;
            while(n != 0){
                if((n & 1) == 1) count++;
                n = n >>> 1;
            }
            return count;
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值