Leetcode201-Bitwise AND of Numbers Range

今天看到Leetcode又有新題了。

原題:

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.

題意:

給定一個範圍[m, n],0 <= m <= n <= 2147483647,求出該範圍內所有數按位與(&)操作後的結果。比如範圍[5, 7],爲5&6&7 = 4。

分析:

如果真的在範圍[m, n]內按順序逐個數字做&操作顯然效率不高。那麼我們可以先列出一些數字去尋找規律:

0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000
9 1001
10 1010
11 1011
12 1100
13 1101
14 1110
15 1111
... ...
由上表不難發現不同位上的變化規律不同。而右移操作>>會抹去末端一位

再看其中的一個區間,舉例[12, 15]:

12 1100 110 11
13 1101 110 11
14 1110 111 11
15 1111 111 11
上表區間中在移位過程中,逐漸抹去最後一位,最終會在某一次移位後區間內所有數的值相同(1101->110->11),移位次數爲2,該範圍內所有數按位與操作以後結果爲1100,即12。由此我們可以知道,低位部分在範圍內按位與操作中會因爲0的存在而消去爲0,只有高位部分會得以保留。因此我們可以用一個count計數器記錄移位次數(即低位0的個數),而最終移位結果均一致時(如例子中最終爲二進制11),即爲其高位部分。此時只需將高位部分復原即可,也就是11->110->1100,做2次向左移位復原。

當然在計算過程中我們並不需要對區間內所有數做這種操作,只需對區間最小值m和最大值n進行操作(因爲區間首尾是區分度最大的兩個數,對區間內所有數做右移時,最有可能不相同的肯定是m和n)。

注意:

當較小的數移位後爲0時,就應該停止循環。最終結果肯定也是0。

如果還有困惑請看Ac代碼。


AC代碼(C++實現):

class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
        int count = 0;//初始化計數器
        while (m && m != n) {//m爲0時或m == n時退出循環
        	++count;//統計低位0的個數
        	m >>= 1; n >>= 1;//抹去低位
        }
        return m << count;//低位復原, 因爲0 << count仍爲0, 因此此處不做區分
    }
};

如代碼或分析有誤請批評指正,歡迎討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章