其他分享
首页 > 其他分享> > 293,数字范围按位与

293,数字范围按位与

作者:互联网

给定范围 [m, n],其中 0 <= m <= n <= 2147483647,返回此范围内所有数字的按位与(包含 m, n 两端点)。

示例 1: 

输入: [5,7]
输出: 4

示例 2:

输入: [0,1]
输出: 0

答案:

1public int rangeBitwiseAnd(int m, int n) {
2    int r = Integer.MAX_VALUE;
3    while ((m & r) != (n & r))
4        r = r << 1;
5    return n & r;
6}

解析:

这题解法其实有多种,理解起来也不是很难,最简单的一种方式就是通过for循环m到n之间的数字,然后再进行与运算,但这种方式显然效率是最差的。上面的这种解法其实很容易理解,我来举个例子比如数字m=1110001, n=1110111(其中这里的m和n都是二进制表示的)我们计算m和n之间所有数字的与运算,我们只需要计算m和n之间最左边相同的数字即可,所以结果为1110000,因为m和n之间数字的后4位要么是0要么是1,只要有一次是0,那么后面的与运算结果都是0。我们再来看另一种解法,也很经典

1public int rangeBitwiseAnd(int m, int n) {
2    while (m < n)
3        n = n & (n - 1);
4    return n;
5}

原理我们都知道了,我们只需要找到m和n最左边相同的数字即可,所以右边的我们可以让他变为0,直到n小于或等于m为止,这里的n=n&(n-1);表示的消去数字n的二进制位中最右边的1,可查看151,位1的个数。这题也算比较经典,下面再来看一种递归的解法

1int rangeBitwiseAnd(int m, int n) {
2    return (n > m) ? (rangeBitwiseAnd(m / 2, n / 2) << 1) : n;
3}

或者还可以换种写法

1int rangeBitwiseAnd(int m, int n) {
2    return (n != m) ? (rangeBitwiseAnd(m / 2, n / 2) << 1) : m;
3}

如果m不等于n,通过递归的方式分解为子问题,然后求解,这种解法也非常经典,一般也是不容易想到的,或者我们还可以再改写一下

1public int rangeBitwiseAnd(int m, int n) {
2    int i = 0; 
3    while (m != n) {
4        m >>= 1;
5        n >>= 1;
6        i++;
7    }
8    return m << i;
9}

上面两种解法的原理其实已经非常相似了,只不过写法有点不同,但本质还是没变,

 

 

 

标签:return,数字,int,rangeBitwiseAnd,1public,按位,293,解法
来源: https://blog.51cto.com/u_4774266/2902570