201. Bitwise AND of Numbers Range

Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive.

For example, given the range [5, 7], you should return 4.


2的整数幂次的数字,例如1,2,4,8,16,32,64,128,256,512,1024,2048……都是二进制只有1位是1的整数,这里求一个区间所有数相与,如果区间的两端“跨越”了2的不同幂次,那么一定是等于0的,例如[6,8],6是110,8是1000,相与必定变成了0。

所以这个问题可以先看看区间的左右端点是否属于2的同一整数幂次范围,直接取log2 判断一下,如果属于桶一个幂次范围,那么可以找一下这个区间所有数的“公共1”所代表的整数,例如区间 [588,623],这个区间里面的整数最高位的公共1所代表的整数是512,相与下来这一位是不会变成0的,处理掉了这个最高位的公共,可以把区间和512作差变成[76,111],这个区间里所有数的最高公共1代表的数字是64,这样区间又可以变成[12,47]。现在这个区间跨越了2的5次幂=32 ,相与出来是会为0的。从以上可以看出,迭代地,选出区间所有数的最高公共1,最后求和就是相与所得。


public  int rangeBitwiseAnd(int m, int n)
	{
		if(m==0&&n==0)
			return 0;
		
		int mfactor=(int) Math.floor(Math.log10(m)/Math.log10(2));
		int nfactor=(int) Math.floor(Math.log10(n)/Math.log10(2));
		if(mfactor!=nfactor)
			return 0;
		
		int common=(int)Math.pow(2, mfactor);
		
		return common+rangeBitwiseAnd(m-common, n-common);
		
		
	}



以下摘自http://www.cnblogs.com/csonezp/p/4587392.html

思路

按位运算,所有数字自然要按二进制形式表达。一组数字按位与时,只有所有数字这一位上都为1时,结果才会为1。如果m=n,那自然结果就是m.下面讨论m!=n的情况。

让我们从最低位开始。
如果这一组数字的最低位不相同的话,那这一位就肯定会被消掉,变成0.如果m!=n,那最低位肯定是要被消掉的,因为最低位肯定会是一个0,一个1.这时,我们可以将m和n都右移一位,将最后一位忽略。

此时,又有了新的一组m和n。如果此时m=n,那结果就是m了。如果不是的话,那可以继续上一段的过程,将m和n右移一位。

重复上述操作,直到m=n。这个时候,从低位往高位所有进行与操作后结果为0的位数都已经被消掉,而高位的数字进行与操作不会发生变化,此时的m或者n再向左移动之前移动的位数,得到的就是这一组数字按位与后的结果。

代码

public int rangeBitwiseAnd(int m, int n) {
    int i=0;
    while(m!=n){
        m>>=1;
        n>>=1;
        i++;
    }
    return m<<i;
    }
}
    


另一种方式

当然,我们还可以用其他方式解决这个问题。做题不能仅仅满足与Accepted,而是要深入的理解这一道题,掌握思路从无到有的过程,并且要试着想一下解决问题的其他方式。

这里的另一种方式,主要用到了n&(n-1)这个式子。初看上去你可能会很迷茫,因为从字面上确实看不出这个式子跟这个题目有什么关系。当然,如果你脑子中二进制各种运算和十进制一样熟悉,那你肯定会知道,这个式子的作用就是消去n的最低位的1。讲解可以看这里

采用这个式子呢,我们的算法可以简化成以下这个形式:

public class Solution {
    public int rangeBitwiseAnd(int m, int n) {
        while(n>m){
            n=n&(n-1);
        }
        return n;
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值