【剑指offer】二进制中1的个数

题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

解题思路

  • 遇到的坑:

    • int的位数,即该用多长的数组去存储二进制位。
    1. Int16: -32768(-216)到 +32767 (216-1)之间的有符号整数。
    2. Int32: -2,147,483,648(-232) 到 +2,147,483,647 (232-1)之间的有符号整数。
    3. Int64 :-9,223,372,036,854,775,808 (-264)到 +9,223,372,036,854,775,807(264-1) 之间的整数。
    4. long long能表示264个数,因为要考虑正负数,所以是 -263~ (263-1)。
    5. int是32位整数,上限是 (231-1),下限是 -231
    • 当int值时-2,147,483,648时,其原码是1000 0000 0000 0000 0000 0000 0000 0000, 反码是:1111 1111 1111 1111 1111 1111 1111 1111,补码是1000 0000 0000 0000 0000 0000 0000 0000,在求补码时产生了溢出。
  • 逻辑:

    1. 正负数处理逻辑不一样,分开讨论。
    2. 声明32位数组,将其初始化为1,第一步用来存放反码(由while循环实现)。
    3. 为了防止在循环中产生溢出(针对-2,147,483,648),需要在while循环结束后再将符号位置为1。
    4. for循环中+1求补码(不对符号位进行操作),求补码的同时记录补码中1的个数。

代码

public class Solution {
    public int NumberOf1(int n) {
        int count = 0;
        if(n >= 0){
            while( n != 0){
                if(n % 2 == 1){
                    count++;
                }
                n = n /2;
            }
        } else {
            count++;
            int arr[] = new int[32];
            for(int i = 1;i<arr.length;i++){
                arr[i] = 1;
            }
            int index = arr.length - 1;
            while( n != 0){
                if((-1) * (n % 2) == 0){
                    arr[index--] = 1;
                } else {
                    arr[index--] = 0;
                }
                n = n /2;
            }
            arr[0] = 1;
            int num = 1;
            for (int i = arr.length - 1; i > 0; i--){
                if(arr[i] + num == 2){
                    arr[i] = 0;
                    num = 1;
                } else if(arr[i] + num == 1){
                    arr[i] = 1;
                    count++;
                    num = 0;
                }
            }
        }
        return count;
    }
}

和同事讨论后的代码

巧妙地利用移位的办法和n做与运算,如果该位是0,则与的结果是0。

public int NumberOf1(int n) {
        int count = 0, i = 0;
        while(i <32){
            if(((1 << i) & n) != 0){
                count++;
            }
            i++;
        }
        return count;
    }

补充说明

对于一个int n,通过下述办法可以求得其二进制

	int count = 0, i = 0;
	while(i <32){
	    System.out.println(n >> i & 1);
	    i++;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值