Python 2816.py
class Solution:
def doubleIt(self, head: Optional[ListNode]) -> Optional[ListNode]:
# gather digits
one = ""
scan = head
while scan:
one += str(scan.val)
scan = scan.next
# double
sys.set_int_max_str_digits(0)
two = str(2 * int(one))
# prepend (at most) one digit
if len(two) > len(one):
head = ListNode(0, head)
# overwrite values
scan = head
for c in two:
scan.val = int(c)
scan = scan.next
return head
Difficulty
and has an acceptance rate of about 61% (300k+ submissions).
Typical patterns to solve this problem:
- Linked List
- Math
- Stack
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The provided implementation defines a Solution class with a single method doubleIt. The method receives the head of a singly-linked list where each node stores a single decimal digit of a non-negative integer, most significant digit first. The goal is to return a new linked list that represents the integer multiplied by two, preserving the original ordering of digits. The algorithm proceeds in four logical phases: digit collection, numeric doubling, optional head extension, and in-place value overwriting.
Digit Collection
The first phase traverses the input list and builds a string representation of the number.
one = ""
scan = head
while scan:
one += str(scan.val)
scan = scan.next
By iterating node-by-node, the code concatenates each digit’s string form to one. This yields a compact textual version of the entire integer without allocating auxiliary data structures beyond the accumulating string.
Numeric Doubling
Once the digit string is assembled, the method converts it to a Python integer, doubles it, and converts the result back to a string.
sys.set_int_max_str_digits(0)
two = str(2 * int(one))
The call to sys.set_int_max_str_digits(0) lifts the default safety limit on the number of digits that can be parsed from a string, allowing the function to handle arbitrarily large inputs without raising a ValueError. The multiplication leverages Python’s built-in arbitrary-precision integer arithmetic, which is implemented in highly optimized C code.
Optional Head Extension
If the doubled value introduces an additional most-significant digit (for example, turning 999 into 1998), the linked list must grow by one node. The code detects this situation by comparing the lengths of the original and doubled strings.
if len(two) > len(one):
head = ListNode(0, head)
When the condition holds, a new node with value 0 is inserted at the front of the list, effectively reserving space for the extra digit that will be written in the next phase.
In-Place Value Overwriting
The final phase walks the (potentially extended) list and overwrites each node’s val with the corresponding digit from the doubled string.
scan = head
for c in two:
scan.val = int(c)
scan = scan.next
Because the list is traversed in the same order as the string, the most-significant digit is placed at the head, preserving the required ordering without constructing a new list structure.
Edge Cases Handled
The algorithm gracefully accommodates the scenario where doubling produces a carry that expands the number of digits. By checking the length of the result string against the original, it ensures that the linked list is extended exactly when needed, preventing off-by-one errors during the overwrite loop.
Another implicit edge case is the handling of very large numbers. The explicit removal of the digit-limit restriction via sys.set_int_max_str_digits(0) allows the method to process inputs whose decimal representation exceeds the default safety threshold, thereby supporting inputs of virtually any size limited only by available memory.
Performance Optimizations
The most notable optimization is the reliance on Python’s native big-integer arithmetic for the multiplication step. This avoids manual per-digit carry handling, which would require additional Python-level loops and condition checks. By delegating the heavy lifting to the interpreter’s C implementation, the code benefits from low-level optimizations such as Karatsuba multiplication for large operands.
Additionally, the use of a single string to accumulate digits reduces the overhead of managing intermediate collections. The conditional insertion of a single leading node avoids unnecessary list reconstruction; only one new node is allocated when the result length grows, keeping memory allocation minimal.
Finally, the direct overwrite of node values eliminates the need to allocate a fresh list for the result, reusing the existing node objects (or the single newly created node) and thereby limiting the number of object creations and garbage-collection events.
ELI5 - Simplified Explanation
Think of the list of numbers like a train where each car holds a single digit. First, the code walks down the whole train from the front to the back, looking at every car one by one. It writes down each digit it sees on a piece of paper to remember the whole number. Once all the digits are collected, it uses math to double that number just like adding it to itself.
After finding the new bigger number, it makes sure there is enough space in the train. If the new number grew extra digits, it adds an empty car to the very front of the line so everything fits perfectly. Finally, the code walks down the train again, but this time it replaces the old ticket on each car with the new digit that belongs there. After painting over all the old numbers with the new ones, the train is finished and ready to go.
Code Quality
Complexity Analysis
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | ||||||||
|---|---|---|---|---|---|---|---|---|
| author | solutions | |||||||
| www | AlgoMonster | Java | Python | C++ | TS | |||
| WalkCCC | Java | Python | C++ | |||||
| leetcode.ca | Java | Python | C++ | Go | TS | |||
| Progiez | Java | Python | C++ | |||||
| github | chandansgowda | Python | ||||||
| charles-wangkai | Java | |||||||
| everthis | JS | |||||||
| fsq | C++ | |||||||
| JoshCrozier | JS | |||||||
| shreymehul | C# | |||||||
| varunu28 | Java | |||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||
| WalkCCC | C++, Python, Java | |||||||
| leetcode.ca | C++, Go, Java, Python, TypeScript | |||||||
| Progiez | C++, Java, Python | |||||||
| chandansgowda | Python | |||||||
| charles-wangkai | Java | |||||||
| everthis | JavaScript | |||||||
| fsq | C++ | |||||||
| JoshCrozier | JavaScript | |||||||
| shreymehul | C# | |||||||
| varunu28 | Java |
Videos
Similar Problems
- problem 369: Plus One Linked List
Solved On The Same Day
- problem 462: Minimum Moves to Equal Array Elements II
- problem 468: Validate IP Address
- problem 831: Masking Personal Information
- problem 874: Walking Robot Simulation
- problem 886: Possible Bipartition
- problem 1754: Largest Merge Of Two Strings
- problem 2055: Plates Between Candles
- problem 2086: Minimum Number of Food Buckets to Feed the Hamsters
- problem 2105: Watering Plants II
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality