【算法】關於 i & (1< >j) 的解釋


一、 i & (1<<j)

  1<<j表示二進制表示的1(即0001)的所有位向左平移j個單位后的數,如j=1,則平移后的結果是0010,此時得到數2。若j=3,平移后的結果是1000,此時得到數8向左平移j位,即表示將原來的數乘上2^j可以類比十進制,所有位左移j位,相當於在后面添了j0,即乘上10^j,在二進制中,即乘上2^j

  &在此處表示按位與,即兩個二進制表示的數,在對應位置上進行取並的操作,都為1時取1,否則取0。如1010(十進制的10)和0101(十進制的5)進行按位與操作后,得到的是0000(十進制的0)。

  i & (1<<j)則表示 i1<<j(即2^j) 按位與后得到的數。1<<j的二進制表示只有第j個位置(從右往左數,從0開始)上的數是1,其余位置上的數是0i1<<j 進行按位與操作時,i的第j個位置是1就返回1<<j(判斷語句中即為true),i的第j個位置是0就返回0(判斷語句中即為false

ex:i=18,j=3
00010010
00001000
________
00000000

具體地,

i=0時,任何j都不滿足。

i=1時,j=0 滿足條件。

i=2時,j=1 滿足條件。

i=3時,j=0,1 滿足條件。

i=4時,j=2 滿足條件。

i=5時,j=0,2 滿足條件。

i=6時,j=1,2 滿足條件。

i=7時,j=0,1,2 滿足條件。

i=8時,j=3 滿足條件。

...

i=2^n-1時,j=0,1,2,...,n-1 滿足條件。

  歸納一下,如果j表示數組a(長度為n)的索引,循環結構如下,則表示依次選取數組a的一個子數組進行操作,直到選到它本身。

for (let i=1; i<1<<n; ++i) {
        for (let j=0; j<n; ++j) {
            if (i & (1<<j)) {}
        }
    }

  例子:LeetCode 2044. 統計按位或能得到最大值的子集數目(中等),代碼參考文獻1

var countMaxOrSubsets = function(nums) {
    let cnt=0,res=0,n=nums.length;
    for (let i=1; i<1<<n; ++i) {
        let tem=0;
        for (let j=0; j<n; ++j) {
            if (i & (1<<j)) {
                tem |= nums[j];
            }
        }
        if (tem>res) {res=tem;cnt=0;}
        if (tem == res) {cnt++;}
    }
    return cnt;
};

例如,當a=[3,1]時,

i=1,j=0時,取[3]tem=3,res=3,cnt=1

i=2,j=1時,取[1]tem=1,res=3,cnt=1

i=3,j=0時,取[3]tem=3;

i=3,j=1時,取[1]tem=3,res=3,cnt=2

返回2。

二、 1 & (i>>j)

  1 & (i>>j)相當於i 右移 j 位后,若為奇數則返回1,若為偶數則返回0。代碼相當於:

let a = i/(2**j);
if (a % 2 == 0) {
	return 0;
} else {
    return 1;
}

i>=0 && i < 2^n ,j>=0 && j<n ,具體地,

i=0時,任何j都不滿足。

i=1 時,j=0滿足條件。

i=2 時,j=1時滿足條件。

i=3 時,j=0,1時滿足條件。

i=4 時,j=2時滿足條件。

i=5 時,j=0,2時滿足條件。

i=6 時,j=1,2時滿足條件。

i=7 時,j=0,1,2時滿足條件。

i=8 時,j=3時滿足條件。

...

i=2^n-1 時,j=0,1,2,...,n-1時滿足條件。

  歸納,1 & (i>>j)i & (1<<j) 的效果一樣,都是依次取出[0,1,2,...,n-1]的子集,直到取到其本身。

參考

1.5904. js 暴力


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM