As explained in comments, you should not have a second if
block that can be executed even when the first if
block had already executed... That second block should only be executed when the first didn't -- so using an else
.
Let's visualise what happens in the faulty code with a very small example. Take as input two lists which each just have one node with value 1.
When the solution code is run, a dummy node New_Node
is created, and then Traversal
is called. We can picture that state as follows:
list1
│
┌──┴─────────┐
│ val: 1 │
New_Node │ next: None │
│ └────────────┘
┌──┴─────────┐
│ val: 0 │
│ next: None │
└──┬─────────┘
│ ┌────────────┐
temp │ val: 1 │
│ next: None │
└──┬─────────┘
│
list2
The first if
block assigns to temp.next
and makes a recursive call: I'll denote the new local variables -- that only live inside that recursive execution context!! -- with accents:
list1'
list1
│
┌──┴─────────┐
│ val: 1 │
New_Node │ next: None │
│ └────────────┘
┌──┴─────────┐
│ val: 0 │
│ next: ──────┐
└──┬─────────┘│
│ │ ┌────────────┐
temp └─┤ val: 1 │
│ next: None │
└──┬─────────┘
│
list2 list2' ───None
temp'
In the recursive execution context, list2'
is None
(a base case), so temp'.next = list1'
is executed and the function returns to the first execution context of Traversal
. Note that in that execution context we still have the original list1
and list2
; recursive executions have their own set of local variables (which happen to have the same names). So coming back from the recursive call, we have this:
list1
│
┌──┴─────────┐
│ val: 1 │
New_Node │ next: None │
│ └─────────┬──┘
┌──┴─────────┐ │
│ val: 0 │ │
│ next: ──────┐ │
└──┬─────────┘│ │
│ │ ┌─────────│──┐
temp └─┤ val: 1 │ │
│ next: ──┘ │
└──┬─────────┘
│
list2
Because of the bug, the second if
block executes too, and there temp.next
is overwritten with temp.next = list1
(that's not how it is supposed to work), and another recursive call is made:
temp'
list1 list1' ───None
│
┌──┴─────────┐
│ val: 1 │
New_Node ┌─┤ next: None │
│ │ └─────────┬──┘
┌──┴─────────┐│ │
│ val: 0 ││ │
│ next: ──────┘ │
└──┬─────────┘ │
│ ┌─────────│──┐
temp │ val: 1 │ │
│ next: ──┘ │
└──┬─────────┘
│
list2
list2'
Also this time the recursive call hits a base case because list1'
is None
. temp'.next
gets assigned list2'
, which creates a problematic cycle, and the recursive call returns:
list1
│
┌──┴─────────┐
│ val: 1 │
New_Node ┌─┤ next: ───┐ │
│ │ └─────────┬│─┘
┌──┴─────────┐│ ││
│ val: 0 ││ ││
│ next: ──────┘ ││
└──┬─────────┘ ││
│ ┌─────────│┴─┐
temp │ val: 1 │ │
│ next: ──┘ │
└──┬─────────┘
│
list2
Things have gone really wrong: here there is no infinite recursion, because I used small lists, but it does show that a list has been created with a cycle. If one of the input lists would have had one more node, then the recursion would get stuck in this cycle (as it passes list1.next
or list2.next
as argument, which is a node that was already visited), finding no end to the list.
The correct algorithm requires that once temp.next
has received a node reference, it should never again be overwritten. Yet this is what happens if you don't avoid the case where the two if
blocks are entered and they are not mutually exclusive.