Java算法之二--二进制1的个数问题--位运算

2 篇文章 0 订阅
2 篇文章 0 订阅

大家好我是M1ko,今天给大家分享的算法是关于二进制运算的问题,说到二进制,一个程序员第一个反应肯定是位运算,这一方面也一直是自己的薄弱点,好的废话不多说开车出发。
首先上题目地址:赛码网
上题目:
这里写图片描述
依旧是高清无码的无厘头题目。这种题目一上来很容易上头,开始钻牛角尖想各种for循环。其实我们要记住一句话:超过双重循环的算法都不是好算法。
这时候我们要转变思路,用n个一来求得十进制必然是十分麻烦的因为总的位数是不确定的,我们是否可以算出十进制中的1的个数呢?当求得的1的个数等于输入的个数那么计数器加一问题便迎刃而解。
答案是肯定的,那么算法应该是怎么样的呢?这时候我们肯定要想到位运算符。>> , << , >>>
我们要计算1的个数必然还要使用一个运算符&,当同一位上的两个数是1的时候,结果是1。但我们不知道究竟有多少位数呀?这是候就要用到位运算符了。
这里给大家分享两种思路:
1.直接算法:

static int BitCount( int n)
    {
        int c =0 ; // 计数器
        while (n >0)
        {
            if((n &1) ==1) // 当前位是1
                ++c ; // 计数器加1
            n >>=1 ; // 移位
        }
        return c ;
    }

举个例子大家就会明白该算法的原理,110101当他与1进行&运算时,可以想象为110101 与 000001进行运算。当最末位为1的时候结果就是1,这时候我们进行右移。最终移动完之后为0跳出循环。
但是大家想一想,Java中的Int有多少位?4字节32位对不对,也就是说我们for循环要进行32次才能结束。是不是不够优雅呢?

2.快速算法:

static int BitCount2(int n){
        int count = 0;
        while(n>0){
            n = n&(n-1);
            count ++;
        }
        return count;
    }

看样子跟上一个算法很相似,但是n&(n-1)是什么鬼?
同样给大家举几个例子,n = 3。转化为二进制是11.3-1=2 23转化为二进制是10,有没有发现呢其实十进制与二进制的一个很大的联系就是最后一位加一减一。很神奇的是他们是相通的。
110101&110100–>110100
110100&110011–>110000
110000&101111–>100000
.
想必聪明的我们都明白了,这个算法的原理其实就是每次循环去掉最末尾的1,这样我们只需要4次循环就可以解决问题了。是不是很神奇呢=-=。

最终题目解法:

import java.util.Scanner;

public class Main {
    private static Scanner cin;

    public static void main(String arg[]){
        cin = new Scanner(System.in);
        int l = cin.nextInt();
        int m = cin.nextInt();
        int r = cin.nextInt();
        if(l>m){
            System.out.println(-1);
            return;
        }
        int i;
        int numCount = 0;
        for(i=l;i<=m;i++){
            if(BitCount2(i)==r){
                numCount++;
            }
        }
        if(numCount==0){
            System.out.println(-1);
        }
        else{
            System.out.println(numCount);
        }

    }
    static int BitCount( int n)
    {
        int c =0 ; // 计数器
        while (n >0)
        {
            if((n &1) ==1) // 当前位是1
                ++c ; // 计数器加1
            n >>=1 ; // 移位
        }
        return c ;
    }
    static int BitCount2(int n){
        int count = 0;
        while(n>0){
            n = n&(n-1);
            count ++;
        }
        return count;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值