ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java篇—二进制中1的个数(思路解析及代码实现)

2019-08-04 18:35:58  阅读:204  来源: 互联网

标签:count Java 二进制 个数 step int flag num 解法


题目描述:

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

解法1思路解析:

step 1:num的二进制的最右边位与1相与,如果不为0,则count加1;

step 2:否则,对1左移一位,继续与num的二进制的最右边数的第二位进行相与;

step 3:依次循环,即可完成。

解法1代码实现:

import java.util.Scanner;
public class Exercise18 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()){
            int num = sc.nextInt();
            int count = NumberOf1(num);
            System.out.println(count);
        }
    }

    private static int NumberOf1(int num) {
        //判断num是否为0
        if(num == 0){
            return 0;
        }
        //记录1的出现次数
        int count = 0;
        int flag = 1;
        //flag一直向左移,当到1000 0000 0000 0000时,如果再左移,就回到了0
        while(flag != 0){
            //num有可能是负数,当它与flag相与的时候,结果小于0,
            //所以只要让两者相与的结果不为0即可
            if((num & flag) != 0){
                count++;
            }
            //flag左移一位
            flag = flag << 1;
        }
        return count;
    }

}

解法1缺陷解析:

循环次数较多,解法1代码的循环次数跟数据类型有关,如果是int型(4字节),那么它在计算机中存储的bit位为32位,如果是short型(2字节),那么它在计算机中存储的bit位为16位,如果数据没有占满整个bit位的话,即使得到我们想要的结果,flag还是要进行左移,直到flag为0,换句话讲,int型的数据,不管它是多大,flag都要左移32位,即循环了32次,对于short型数据,flag要左移16位,即循环了16次。

 

解法2思路解析:

step 1:num的二进制与1相与,如果不为0,则count加1;

step 2:否则,对num无符号右移一位,继续与1进行相与;

step 3:依次循环,即可完成。

解法2代码实现:

import java.util.Scanner;
public class Exercise18 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()){
            int num = sc.nextInt();
            int count = NumberOf2(num);
            System.out.println(count);
        }
    }

    private static int NumberOf2(int num) {
        //判断num是否为0
        if(num == 0){
            return 0;
        }
        //记录1的出现次数
        int count = 0;
        int flag = 1;
        while(num != 0){
            //num有可能是负数,当它与flag相与的时候,结果小于0,
            //所以只要让两者相与的结果不为0即可
            if((num & flag) != 0){
                count++;
            }
            //num无符号右移一位,如果改成有符号右移,正数没影响,负数会使系统陷入死循环
            num = num >>> 1;
        }
        return count;
    }

解法2缺陷解析:

(1)对于解法2,如果不注意将代码写成有符号右移,即num = num >> 1,拿到的num又恰好是个负数(负数,在进行右移的时候,最高位会进行补位运算,不管右移多少次,始终都会出现这一个1—符号位的1,这个时候就会造成一个负数得到无数个1),那么将会使系统陷入死循环。

(2)对原数字进行了更改,不利于后期使用。

 

解法3思路解析:

step 1:如果一个整数不为0,那么这个整数的二进制至少有一位是1;

step 2:如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话),更改后的1(1变为0)的前面的其余位数不受影响;

step 3:num 与 num - 1进行相与,消除该数二进制位最右边的1;

step 4:依次循环,即可完成。

解法3代码实现:

import java.util.Scanner;
public class Exercise18 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()){
            int num = sc.nextInt();
            int count = NumberOf3(num);
            System.out.println(count);
        }
    }

    private static int NumberOf3(int num) {
        //判断num是否为0
        if(num == 0){
            return 0;
        }
        //记录1的出现次数
        int count = 0;
        //当num不为0时,其它任意整数的二进制至少有一个1,进入循环后,count先加1
        while(num != 0){
            count++;
            /**
             * num-1,如果n的二进制右边数第一位是1,则变为0,如果到某几位才为1时,
             * 如:0110 0100,则最右边的1变为0,
             * 原先1的右边的00都变为11 即0110 0011,然后与num相与;
             * 得到的值正好是:0110 0000,(刚好消除了最右边的那一个1)
             * 最终结论,num & (num - 1)只会将最右边的1变为0
             */
            num = num & (num - 1);
        }
        return count;
    }

解法3缺陷解析:

对原数字进行了更改,不利于后期使用。

 

题目总结:

(1)解法1的循环次数较多,但没有更改原数据;

(2)解法2更改了原数据,如果代码写成有符号右移,对于负数,会造成系统的死循环;

(3)解法3更改了原数据。

 

计算机中数的存储形式:

https://mp.csdn.net/postedit/98472451

Java移位运算符:

https://mp.csdn.net/postedit/98472473

心灵鸡汤:考虑一千次,不如去做一次;犹豫一万次,不如实践一次;华丽的跌倒,胜过无谓的彷徨,将来的你,一定会感谢现在奋斗的自己。

标签:count,Java,二进制,个数,step,int,flag,num,解法
来源: https://blog.csdn.net/weixin_43761659/article/details/98470411

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有