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
constCURRENT_INDEX='current_index',CURRENT_INDEX_COLOR='gold';functionvisMainFunction(s){initClassProperties();if(s[0]==='0'){notification(`❌ <b>Invalid input:</b> Cannot start with <code>'0'</code>. Returning <b>0</b>.`);return0;}colorSchemaAndExplanationNotifications();startBatch();const sVis = VisArray.from([...s]).options({label:'s'});let prevWays =1;let lastWays =1;makeVisVariable(prevWays).options({label:'prevWays'}).createVis();makeVisVariable(lastWays).options({label:'lastWays'}).createVis();let currentIndex =1;makeVisVariable(currentIndex).registerAsIndexPointer(sVis,CURRENT_INDEX);endBatch();notification(`
⚙️ <b>Initialization before iteration</b>:
<ul>
<li><b>prevWays = 1</b>: Represents the number of ways to decode up to the <b>character before the last evaluated one</b> — initially, the empty prefix has one valid decoding.</li>
<li><b>lastWays = 1</b>: Represents the number of ways to decode up to the <b>last evaluated character</b> — the first digit (already checked to be non-zero) forms one valid decoding.</li>
</ul>
▶️ We’ll now iterate through the string starting from index <b>1</b> (the second character).<br/><br/>
At each step, we’ll determine how many new decoding combinations can be formed
based on the validity of the <b>${makeColoredSpan("current digit",CURRENT_INDEX_COLOR)}</b> and the pair formed with the previous one.
We then update our running counts accordingly to reflect all valid ways so far.
`);while(currentIndex < s.length){startPartialBatch();let newWays =0;makeVisVariable(newWays).options({label:'newWays'}).createVis();const singleDigit = s[currentIndex];const twoDigit = s[currentIndex -1]+ s[currentIndex];notification(`📌 Analyzing single digit <b>${makeColoredSpan('"'+ singleDigit +'"',CURRENT_INDEX_COLOR)}</b> at index <b>${makeColoredSpan(currentIndex,CURRENT_INDEX_COLOR)}</b> and two-digit pair <b>"${twoDigit}"</b> from indices <b>${currentIndex -1}</b> and <b>${makeColoredSpan(currentIndex,CURRENT_INDEX_COLOR)}</b>.`);// Single-digit decode checkif(singleDigit !=='0'){
newWays += lastWays;notification(`✅ <b>Single-digit decode is valid</b>:
<ul>
<li>Digit <b>${makeColoredSpan('"'+ singleDigit +'"',CURRENT_INDEX_COLOR)}</b> represents letters (1–9), meaning each valid decoding up to the <b>last evaluated character</b> (whose count is stored in <b>lastWays = ${lastWays}</b>) can be extended by this digit.</li>
<li>Therefore, we increment <b>newWays</b> by <b>lastWays = ${lastWays}</b>, resulting in <b>newWays = ${newWays}</b>.</li>
</ul>`);}else{notification(`⚠️ <b>Single-digit decode invalid</b>:
<ul>
<li>Digit <b>${makeColoredSpan('"0"',CURRENT_INDEX_COLOR)}</b> cannot decode to any letter alone.</li>
<li>Hence, it does not contribute to <b>newWays</b>.</li>
</ul>`);}// Two-digit decode checkif(twoDigit >="10"&& twoDigit <="26"){
newWays += prevWays;notification(`✅ <b>Two-digit decode is valid</b>:
<ul>
<li>Pair <b>"${twoDigit}"</b> can represent letters (10–26), meaning each valid decoding up to the <b>character before the last evaluated one</b> (whose count is stored in <b>prevWays = ${prevWays}</b>) can be extended by this pair.</li>
<li>Therefore, we increment <b>newWays</b> by <b>prevWays = ${prevWays}</b>, resulting in <b>newWays = ${newWays}</b>.</li>
</ul>`);}else{notification(`⚠️ <b>Two-digit decode invalid</b>:
<ul>
<li>Pair <b>"${twoDigit}"</b> is not between 10 and 26.</li>
<li>Hence, it does not contribute to <b>newWays</b>.</li>
</ul>`);}notification(`📌 <b>Updating decoding counts</b>:
<ul>
<li>Shift variables forward:</li>
<ul>
<li><b>prevWays</b> ← previous <b>lastWays (${lastWays})</b></li>
<li><b>lastWays</b> ← new calculated <b>newWays (${newWays})</b></li>
</ul>
</ul>`);
prevWays = lastWays;
lastWays = newWays;
currentIndex +=1;endBatch();}notification(`🏁 <b>Finished!</b> The total number of ways to decode <b>"${s}"</b> is stored in <b>lastWays = ${lastWays}</b>.`);return lastWays;}functioncolorSchemaAndExplanationNotifications(){explanationNotification();notification(`
🎨 <b>Color Schema</b>:
<ul>
<li><span style="background-color:${CURRENT_INDEX_COLOR}; padding:2px 6px; border-radius:4px;"> </span>
— highlights the <b>current index/character</b> being evaluated.</li>
</ul>
These colors help distinguish which character is currently under evaluation
as we iterate through the string and update decoding counts.
`);}functioninitClassProperties(){setClassProperties(CURRENT_INDEX,{backgroundColor:CURRENT_INDEX_COLOR});}
Solution explanation
Solution explanation
Approach
Approach (Dynamic Programming with Two Running Counts)
We compute the number of decodings of the input string s using a
constant-space DP that scans left-to-right. At each step, we consider whether the
current character can form a valid single-digit code (1–9) and whether the
previous+current characters can form a valid two-digit code (10–26).
State (running variables):
lastWays — number of ways to decode up to the last evaluated character.
prevWays — number of ways to decode up to the character before the last evaluated one.
Initialization / Base cases:
If s[0] = '0', there are no valid decodings → return 0.
Otherwise, set prevWays = 1 (empty prefix has one way) and lastWays = 1 (a non-zero first digit has exactly one decoding).
Transition (for each index i from 1 to s.length-1):
Start newWays = 0.
Single-digit check: If s[i] ∈ {'1'..'9'}, add lastWays to newWays
(any decoding up to the last evaluated character can be extended by this valid digit).
Two-digit check: If s[i-1]s[i] ∈ {"10".."26"}, add prevWays to newWays
(any decoding up to the character before the last evaluated one can be extended by this valid pair).
Shift the window forward: prevWays = lastWays, lastWays = newWays.
Processing order: Left-to-right, updating only the two running counts. No DP array is stored.
Result: After the scan, lastWays is the total number of decodings of the whole string.
Edge Conditions
Leading zero (s[0] = '0') is invalid → immediately return 0.
Single zeros never decode alone; they only participate in valid pairs "10" or "20".
Time Complexity
Each character in the input string is processed once, and for each position, we perform a constant amount of work.
Therefore, the overall time complexity is O(n), where n is the length of the string.
Space Complexity
Since we only keep track of just a few variables, the space complexity is O(1).
Input-1
Visucodize editorial solution titled JS Solution for LeetCode's Decode Ways 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/decode-ways.