Leetcode 201 Bitwise AND of Numbers Range 區間內整數按位與

原題地址

https://leetcode.com/problems/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.
給出一個區間 [m, n],其中0 <= m <= n <= 2147483647,即m,n都是非負整數,返回這個區間內所有整數的按位與結果,包括m和n在內.

For example, given the range [5, 7], you should return 4.
例如,給出區間 [5, 7],你應該返回4.

5 --- 0000 0101
6 --- 0000 0110
7 --- 0000 0111
_______________
4 --- 0000 0100

解題思路

顯然,暴力解決方法是從m開始直到n求按位與,但很明顯這太慢了,雖然時間複雜度是O(n),但顯然不是一個好的解法.我們可以注意到這樣一點,在數字加1的時候,最低位肯定會從0變成1,或者從1變成0,不管哪樣,兩個數的最低位中勢必有一個0,而一旦出現了一個0,這一位上的按位與結果將永遠爲0.假如在m->n的增加過程中,m的最高位也發生了改變,那麼m之下的所有位都變成過0.那樣的話結果也只能是0了.我們再來看兩個相鄰的數,m,m+1,在+1的時候,改變的位可能是多個,而且改變一定是0->1或者1->0,因此,發生改變的位在求AND操作後結果一定是0,因此只有那些沒有改變的位才能在AND結果之後保留下來,於是對於m和m+1我們只要找到從最高位開始完全相同的位.同樣對於m+1和m+2也是如此.但是如果我們真的按照這個邏輯來的話就跟暴力解法一樣了.我們可以發現,對於m和n,找到他們從最高位開始完全相同的位,就是我們需要的結果.這也不難理解,m和n假如在最高位到x位之間的二進制位完全相同,這就說明在遞增的過程中+1的操作永遠沒有改變過這些位,而相反第x-1到最後一位都至少改變過一次,而改變一定是0->1或者1->0,就是說在着m-n+1個操作數中至少有一個的第i位(i>=0 && i<=x-1)爲0.因此,第x-1位之下全都爲0,m和n從最高位開始的連續相同部分就是我們要的結果.

算法

  1. 偏移量offset = 0
  2. 當m,n都不爲0時執行循環,進入3
  3. 如果m==n,返回m << offset,否則4
  4. m,n均右移一位,offset加1,進入3

代碼

int rangeBitwiseAnd(int m, int n) {   
    int offset = 0;
    while (m && n) {
        if (m == n) return m << offset;
        m >>= 1;
        n >>= 1;
        ++offset;
    }
    return 0;
}

完整代碼 https://github.com/Orange1991/leetcode/blob/master/201/c/main.c


2015/8/6

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