LeetCodeOJ_201_Bitwise AND of Numbers Range



答題鏈接


題目:


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

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


分析

     這道題要求計算一定範圍內所有整數的按位與,常規方法,可以對於該範圍內的所有整數依次進行按位與操作,但這種方法的時間複雜度爲O(N)。通過對數據進行分析,其實我們可以使用更省時的方法。

     1首先,先看個簡單例子:


                                                                                             

Fig.1

        Fig.1呈現的是0~8的二進制表示,我們可以發現:

從右到左第0位的01交替出現,也就是說對於任意2個或2個以上的連續整數,這一位必然會同時出現01,而要出現0->1->0或者1->0->0的情況,至少得要3個連續整數。

從右到左第1位的1每隔2個數交替出現,也就是說對於任意大於等於3個的連續整數,這一位必然會同時出現01,而要出現0->1->0或者1->0->0的情況,至少得要4個連續整數。

從右到左第2位的1每隔4個數交替出現,也就是說對於任意大於等於5個的連續整數,這一位必然會同時出現01,而要出現0->1->0或者1->0->0的情況,至少得要6個連續整數。

……

按照這個規律,我們可以總結出:

a:對於任意大於等於2^n+1個的連續整數,從右到左的第0~n位,每一位必然會同時出現01

b:對於第n位,如果要出現0->1->0或者1->0->0的情況,至少得要2^n+2個連續整數才行。

2)其次,對於按位與,只有當某一位的值全部爲1,它的計算結果纔可能爲1(1&1=11&0=00&0=0)

3)最後,要對範圍[m,n]內的所有整數進行按位與運算,那麼,根據(2),我們可以得出,對於從右到左的第x位,除非[m,n]範圍內的所有整數的第x位值都爲1,最終的結果result的第x位值纔可能爲1

(1)a可知,對於大於等於(2^x+1)個的連續整數,從右到左的第0~x位,每一位必然會同時出現01,也就是說reslut的第0~x位必然爲0

[m,n]共包含了len=n-m+1個連續整數,所以,只需要求解出最大的那個x值,即滿足Eq.1,便可以確定後reslut的第0~x位的值。

                                                                  2^(x+1)+1>len>=2^x+1                                     (1)

此外,對於[m,n]範圍中的連續整數,對於前面的任意一位y(y>x),只可能出現0->11->00->01->1的情況。(爲什麼呢?反證:假設出現了0->1->0或者1->0->0的情況,由(1)b可知,len>=2^y+2,而y>x,這和Eq.1相矛盾。)所有,我們要想確定前面每一位的result值,只需要對mn進行&運算即可。

綜上,本題的解決方法爲:

  1. 計算len(len= n-m+1)

  2. 計算x使得2^(x+1)+1>len>=2^x+1

  3. 計算m&n;

  4. 計算result,其二進制值爲m&n並將後x位賦值爲0

(畫外音:在腦袋裏想的時候感覺挺簡單的,可用文字卻發現怎麼也描述不清楚……是我的語言組織能力太爛了嗎??囉嗦了一大堆,也不知道說清楚了沒……=_=b


代碼


<span style="font-size:14px;"><span style="font-family:System;font-size:14px;">class Solution {
public:
    int rangeBitwiseAnd(int m, int n) {
        
        if(m<0||n>2147483647)
           return 0;
        if(n<m)
           return 0;
           
        int len=n-m+1-1;
        int bSize_len=-1;
        while(len!=0)
        {
            len=len/2;
            bSize_len++;
        };
        int result=m&n;
		for(int i=0;i<=bSize_len;i++)
			result&=~(1<<i);
        
        return result;
    }
};
</span></span>


總結:


1、位移動操作符<<>>爲什麼會失效?


最初,我使用如下代碼計算result

<span style="font-size:14px;"><span style="font-family:System;font-size:14px;">n>> bSize_len;
m>> bSize_len;
int result=m&n;
result<< bSize_len;
</span></span>

但調試發現,右移運算符卻沒有被執行?




發佈了32 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章