JZ11---二进制中1的个数

题目

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

思路

  输出了一个32位二进制的数。说明,暗含的说明了,取值范围在4个字节。那么在4个字节,就可以用int类型去接受这样一个整数。
  十进制转二进制,我们用除2再取出余数进行获取1的个数。

  1. 关于正数
    我们可以直接对其进行计算。动态获取,无需存储。
    优化: 运用移位运算符。

    1. 右移1位相当于除以2 右移2位除以4
    2. 左移1位等于乘2 左移2位等于乘4

    样例

		int n = 8;
		// 计算8位的二进制
		for(int i = 7;i >= 0;i--) {
			System.out.print((n >> i) & 1 );
		}
  1. 关于负数
    我们需要对其进行转换一下。因为我们的所有数据在计算机底层是以补码的形式,那么有的人就会问了为什么正数,不需要?因为正数的原、反、补是一模一样的。
    1. 原码 —> 反码(除了符号位不变其余取反) —> 补码(反码 + 1)
    2. 因此,对于负数的产生我们需要用一个容器进行一个存储,因为后面需要对反码 + 1

AC代码

import java.util.Stack;
public class Solution {
    public int NumberOf1(int n) {
        int sum = 0;
		if(n > 0) {
			
			while(n > 0) {
				if(n % 2 == 1)
					sum++;
				n = n / 2;
			}	
			
		}else if(n == 0) {
			return sum;
		}else {
			// 先让他变成正数。
			n = 0 - n;
			// 因为,我们都知道,十进制转二进制。
			// 先计算出来的值。其实在后面。因此用到了堆栈
			Stack<Integer> s = new Stack();
			while(n > 0) {
				s.push((n % 2));
				n = n / 2;
			}	
			int t = s.size();
			// 为了考虑到 整数最小的时候。会产生溢出。因此数组长度为:33
			int[] a = new int[33];
			// 初始化。符号位和溢出位
			a[0] = 0;
			a[1] = 1;
			
			// 原码
			for(int i = 32 - t + 1 ; i <= 32  ; i++) {
				a[i] = s.pop();
			}
			// 反码。除了符号位,其他为全取反
			for(int i = 2;i <= 32 ; i++) {
				if(a[i] == 1)
					a[i] = 0;
				else
					a[i] = 1;
			}
			// 补码。反码 + 1
			// 偷了一个懒。数最后一个0的位置。0的位置置1。后面的置0
			t = 32;
			// 1 + 1 = 10  
			// 本位:0
			// 进位:1
			while(true) {
				if(a[t] == 0) {
					a[t] = 1;
					break;
				}
				a[t] = 0;
				t--;
			}
			// 数1的个数
			// 注意:整数最小值的时候。符号位会产生进位。
			// 个人觉得,理论上不应该加上最后的进位。因为如果算上就是33个二进制数了
			
			for(int i = 0; i <= 32;i++) {
				if(a[i] == 1)
					sum++;
			}
			//System.out.println(Arrays.toString(a));
			
		}
		
		return sum;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值