Leetcode338. 比特位计数
Leetcode338. 比特位計數
題目:
給你一個整數 n ,對于 0 <= i <= n 中的每個 i ,計算其二進制表示中 1 的個數 ,返回一個長度為 n + 1 的數組 ans 作為答案。
示例 1:
輸入:n = 2 輸出:[0,1,1] 解釋: 0 --> 0 1 --> 1 2 --> 10示例 2:
輸入:n = 5 輸出:[0,1,1,2,1,2] 解釋: 0 --> 0 1 --> 1 2 --> 10 3 --> 11 4 --> 100 5 --> 101題解:
方案一:動態規劃——最低設置位
定義正整數 xxx 的「最低設置位」為 xxx 的二進制表示中的最低的 1 所在位。例如,101010101010 的二進制表示是 1010(2)1010_{(2)}1010(2)?,其最低設置位為 2,對應的二進制表示是 10(2)10_{(2)}10(2)?。
令 y=x&(x?1)y=x~\&~(x-1)y=x?&?(x?1),則 yyy 為將 xxx 的最低設置位從 1 變成 0 之后的數,顯然 0≤y<x0 \le y<x0≤y<x,bits[x]=bits[y]+1\textit{bits}[x]=\textit{bits}[y]+1bits[x]=bits[y]+1。因此對任意正整數 xxx,都有 bits[x]=bits[x&(x?1)]+1\textit{bits}[x]=\textit{bits}[x~\&~(x-1)]+1bits[x]=bits[x?&?(x?1)]+1。
遍歷從 1 到 nnn 的每個正整數 iii,計算 bits\textit{bits}bits 的值。最終得到的數組 bits\textit{bits}bits 即為答案。
方案二:動態規劃——最高有效位
當計算 iii 的「一比特數」時,如果存在 0≤j<i0 \le j<i0≤j<i,jjj 的「一比特數」已知,且 iii 和 jjjj 相比,iii 的二進制表示只多了一個 1,則可以快速得到 iii 的「一比特數」。
令 bits[i]\textit{bits}[i]bits[i]表示 iii 的「一比特數」,則上述關系可以表示成:bits[i]=bits[j]+1\textit{bits}[i]= \textit{bits}[j]+1bits[i]=bits[j]+1。
對于正整數 xxx,如果可以知道最大的正整數 yyy,使得 y≤xy \le xy≤x 且 yyy 是 2的整數次冪,則 yyy 的二進制表示中只有最高位是 1,其余都是 0,此時稱 yyy 為 xxx 的「最高有效位」。令 z=x?yz=x-yz=x?y,顯然 0≤z<x0 \le z<x0≤z<x,則 bits[x]=bits[z]+1\textit{bits}[x]=\textit{bits}[z]+1bits[x]=bits[z]+1。
為了判斷一個正整數是不是 2 的整數次冪,可以利用按位與運算的性質。如果正整數 yyy 是 2 的整數次冪,則 yyy 的二進制表示中只有最高位是 1,其余都是 00,因此 y&(y?1)=0y~\&~(y-1)=0y?&?(y?1)=0。由此可見,正整數 yyy 是 2 的整數次冪,當且僅當 y&(y?1)=0y~\&~(y-1)=0y?&?(y?1)=0。
顯然,0 的「一比特數」為 0。使用 highBit\textit{highBit}highBit 表示當前的最高有效位,遍歷從 1 到 nnn 的每個正整數 iii,進行如下操作。
如果 i&(i?1)=0i~\&~(i-1)=0i?&?(i?1)=0,則令 highBit=i\textit{highBit}=ihighBit=i,更新當前的最高有效位。
iii比 i?highBiti-\textit{highBit}i?highBit的「一比特數」多 1,由于是從小到大遍歷每個整數,因此遍歷到 iii 時,i?highBiti-\textit{highBit}i?highBit 的「一比特數」已知,令 bits[i]=bits[i?highBit]+1\textit{bits}[i]=\textit{bits}[i-\textit{highBit}]+1bits[i]=bits[i?highBit]+1。
最終得到的數組 bits\textit{bits}bits 即為答案。
方案三:動態規劃——最低有效位
方法二需要實時維護最高有效位,當遍歷到的數是 2 的整數次冪時,需要更新最高有效位。如果再換一個思路,可以使用「最低有效位」計算「一比特數」。
對于正整數 xxx,將其二進制表示右移一位,等價于將其二進制表示的最低位去掉,得到的數是
?x2?\lfloor \frac{x}{2}\rfloor?2x??。
如果 bits[?x2?]\textit{bits}\big[\lfloor \frac{x}{2} \rfloor\big]bits[?2x??]的值已知,則可以得到 bits[x]\textit{bits}[x]bits[x] 的值:
如果 xxx是偶數,則 bits[x]=bits[?x2?]\textit{bits}[x]=\textit{bits}\big[\lfloor \frac{x}{2} \rfloor\big]bits[x]=bits[?2x??];
如果 xxx 是奇數,則 bits[x]=bits[?x2?]+1\textit{bits}[x]=\textit{bits}\big[\lfloor \frac{x}{2} \rfloor\big]+1bits[x]=bits[?2x??]+1。
上述兩種情況可以合并成:bits[x]\textit{bits}[x]bits[x] 的值等于 bits[?x2?]\textit{bits}\big[\lfloor \frac{x}{2} \rfloor\big]bits[?2x??]的值加上 xxx 除以 2 的余數。
由于 ?x2?\lfloor \frac{x}{2} \rfloor?2x??可以通過 x>>1x >> 1x>>1 得到,xxx 除以 2 的余數可以通過 x&1x~\&~1x?&?1 得到,因此有:bits[x]=bits[x>>1]+(x&1)\textit{bits}[x]=\textit{bits}[x>>1]+(x~\&~1)bits[x]=bits[x>>1]+(x?&?1)。
遍歷從 1 到 nnn 的每個正整數 i,計算 bits\textit{bits}bits 的值。最終得到的數組 bits\textit{bits}bits 即為答案。
java代碼:
/*** @param n* @return*/public static int[] countBits(int n) {int[] dp = new int[n + 1];for (int i = 1; i <= n; i++) {dp[i] = dp[i & (i - 1)] + 1;}return dp;}/*** * @param n* @return*/public static int[] countBits2(int n) {int[] dp = new int[n + 1];int highbit = 0;for (int i = 1; i <= n; i++) {if ((i & (i - 1)) == 0) {highbit = i;}dp[i] = dp[i - highbit] + 1;}return dp;}/**** @param n* @return*/public static int[] countBits3(int n) {int[] dp = new int[n + 1];for (int i = 1; i <= n; i++) {dp[i] = dp[i >> 1] + (i & 1);}return dp;}總結
以上是生活随笔為你收集整理的Leetcode338. 比特位计数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 艾宾浩斯遗忘曲线PHP,艾宾浩斯遗忘曲线
- 下一篇: tunel凋亡试剂盒说明书_急求!!罗氏