LeetCode刷题日记 2020/8/23

题目描述

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

示例 1:

输入: [5,7]
输出: 4
示例 2:

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

题目来源:https://leetcode-cn.com/problems/bitwise-and-of-numbers-range/


自己做的时候暴力破解的 逛评论区发现一个很巧妙的解法: 通过按位与运算来解 代码如下:

我们只需要一个经常用的一个思想,去考虑子问题。我们现在要做的是把从 m 到 n 的所有数字的 32 个比特位依次相与。直接肯定不能出结果,如果要是只考虑 31 个比特位呢,还是不能出结果。然后依次降低规模,30、29 ... 3,2 直到 1。如果让你说出从 m 到 n 的数字全部相与,最低位的结果是多少呢?

最低位会有很多数相与,要么是 0 ,要么是 1,而出现了 0 的话相与的结果一定会是 0。

只看所有数的最低位变化情况,m 到 n 的话,要么从 0 开始递增,01010101...,要么从 1 开始递增 10101010...。

因此,参与相与的数中最低位要么在第一个数字第一次出现 0 ,要么在第二个数字出现第一次出现 0 。

如果 m < n,也就是参与相与的数字的个数至少有两个,所以一定会有 0 的出现,所以相与结果一定是 0。

看具体的例子,[5,7]。


最低位序列从 1 开始递增, 也就是最右边的一列 101

m 5 1 0 1
  6 1 1 0
n 7 1 1 1
        0

此时 m < n,所以至少会有两个数字,所以最低位相与结果一定是 0。

解决了最低位的问题,我们只需要把 m 和 n 同时右移一位。然后继续按照上边的思路考虑新的最低位的结果即可。

而当 m == n 的时候,很明显,结果就是 m 了。

代码中,我们需要用一个变量 zero 记录我们右移的次数,也就是最低位 0 的个数。

public int rangeBitwiseAnd(int m, int n) {
    int zeros = 0;
    while (n > m) {
        zeros++;
        m >>>= 1;
        n >>>= 1;
    }
    //将 0 的个数空出来
    return m << zeros;
}

作者:windliang
链接:https://leetcode-cn.com/problems/bitwise-and-of-numbers-range/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--41/

posted @ 2020-08-23 10:09  seizedays  阅读(99)  评论(0编辑  收藏  举报