-
We want to compute, for every integer
iin the range[0, n], the number of 1 bits (set bits) in the binary representation ofi. We store each result in an arrayonesCountwhereonesCount[i]= βnumber of 1βs in the binary representation ofiβ. -
Key idea β reuse work by removing the last bit:
For any integercurrentNum, its binary form can be split into:
(binary prefix) Β· (last bit)
The number of 1βs in the binary representation ofcurrentNumequals the number of 1βs in the binary prefix plus the value of the last bit. Since we fillonesCountin increasing order, the count of 1βs in the binary prefix must already be stored in the DP array. The index for this prefix is the decimal value of the prefix itself, which we callshiftedNum, computed ascurrentNum >> 1. The last bit (denotedlastBit) is obtained usingcurrentNum & 1. Therefore, the count of 1βs incurrentNumis simply:
onesCount[currentNum] = onesCount[shiftedNum] + lastBit. -
Dynamic programming relation:
We buildonesCountin increasing order so thatonesCount[shiftedNum]is always known before computingonesCount[currentNum].shiftedNum = currentNum >> 1lastBit = currentNum & 1onesCount[currentNum] = onesCount[shiftedNum] + lastBit
-
Building the table:
- Initialize
onesCountwithn + 1entries. - Set
onesCount[0] = 0. - For each
currentNumfrom1ton, apply the formula above.
- Initialize
Counting Bits - JS Solution
JSEditorial
Editorial solutions and visualizations are prepared with care, but we do not guarantee 100% accuracy or completeness. Please use your own judgment to verify results. Visucodize is not responsible for decisions made based on this content.
Solution code
const DONE = 'done', DONE_COLOR = 'green';
const CURRENT_NUM = 'current_num', CURRENT_NUM_COLOR = 'blue';
const SHIFTED_NUM = 'shifted_num', SHIFTED_NUM_COLOR = 'orange';
function visMainFunction(n) {
initClassProperties();
startBatch();
const onesCount = new VisArray(n + 1);
onesCount[0] = 0;
onesCount.makeVisManagerForIndex(0).addClass(DONE);
endBatch();
explanationAndColorSchemaNotifications();
for (let currentNum = 1; currentNum <= n; currentNum++) {
startPartialBatch();
const numVm = onesCount.makeVisManagerForIndex(currentNum).addClass(CURRENT_NUM);
const shiftedNum = currentNum >> 1;
const lastBit = currentNum & 1;
explainComputationStep(onesCount, currentNum, shiftedNum, lastBit);
onesCount[currentNum] = onesCount[shiftedNum] + lastBit;
numVm.removeClass(CURRENT_NUM).addClass(DONE);
endBatch();
}
notification(`π <b>Completed!</b> The final result is stored in <code>onesCount</code>. β
`);
return onesCount;
}
function explainComputationStep(onesCount, currentNum, shiftedNum, lastBit) {
const shiftedNumVm = onesCount.makeVisManagerForIndex(shiftedNum).addClass(SHIFTED_NUM);
notification(`
π <b>Calculating the number of 1βs in
${makeColoredSpan(`currentNum (${currentNum}) (in binary: ${currentNum.toString(2)})`, CURRENT_NUM_COLOR)}</b>, and storing the result in
<code>onesCount[${makeColoredSpan(`currentNum (${currentNum})`, CURRENT_NUM_COLOR)}]</code>:
<ul>
<li>
Binary prefix without the last bit is
${makeColoredSpan('shiftedNum', SHIFTED_NUM_COLOR)} = ${makeColoredSpan('currentNum', CURRENT_NUM_COLOR)} >> 1 =
<b>${makeColoredSpan(`${shiftedNum} (in binary: ${shiftedNum.toString(2)})`, SHIFTED_NUM_COLOR)}</b>
</li>
<li>
Last bit of <code>currentNum</code> (<code>currentNum & 1</code>) is <b>${lastBit}</b>
</li>
<li>
The number of 1βs in
${makeColoredSpan(`currentNum (${currentNum})`, CURRENT_NUM_COLOR)}
is equal to:
<br>
<b>β’ the number of 1βs in the prefix (stored in
onesCount[
${makeColoredSpan(`shiftedNum (${shiftedNum})`, SHIFTED_NUM_COLOR)}
])</b>
<br>
<b>β’ plus the last bit (${lastBit})</b>
<br><br>
Therefore:
<br>
<code>
onesCount[${makeColoredSpan(`currentNum (${currentNum})`, CURRENT_NUM_COLOR)}] =
onesCount[${makeColoredSpan(`shiftedNum (${shiftedNum})`, SHIFTED_NUM_COLOR)}] (${onesCount[shiftedNum]}) + ${lastBit}
= <b>${onesCount[shiftedNum] + lastBit}</b>
</code>
</li>
</ul>
`);
shiftedNumVm.removeClass(SHIFTED_NUM);
}
function initClassProperties() {
setClassProperties(DONE, { backgroundColor: DONE_COLOR });
setClassProperties(CURRENT_NUM, { borderColor: CURRENT_NUM_COLOR });
setClassProperties(SHIFTED_NUM, { borderColor: SHIFTED_NUM_COLOR });
}
function explanationAndColorSchemaNotifications() {
explanationNotification();
notification(`
<b>π¨ Visual Cues (Color Schema)</b>
<ul>
<li>
${makeColoredSpan('Computed entry', DONE_COLOR)} β
highlighted with a <b>${DONE_COLOR} background</b> to mark cells in
<code>onesCount</code> whose values are already finalized.
</li>
<li>
${makeColoredSpan('Current number', CURRENT_NUM_COLOR)} β
highlighted with a <b>${CURRENT_NUM_COLOR} border</b> to show
the index <code>currentNum</code> whose count of 1βs is being computed.
</li>
<li>
${makeColoredSpan('Shifted number', SHIFTED_NUM_COLOR)} β
highlighted with a <b>${SHIFTED_NUM_COLOR} border</b> to show
the index <code>shiftedNum = currentNum >> 1</code> whose value is reused
in the DP formula.
</li>
</ul>
`);
}Solution explanation
Solution explanation
Approach
Time Complexity
We iterate once from
1 to n, and each step performs only constant-time
operations using the dynamic programming relation.
Therefore, the overall time complexity of the algorithm is O(n).Space Complexity
O(n) β We store one computed value for each integer from 0 to n in the output array.Visucodize editorial solution titled JS Solution for LeetCode's Counting Bits coding problem. Includes code and may include explanation. You can animate the code step by step using the provided input by clicking the run button, or fork it locally to update the code and input for custom visualization. View the original problem at https://leetcode.com/problems/counting-bits.