Search code examples
pythonvariableslinked-listvariable-assignmentsingly-linked-list

Does python multivariable assignment order mattering?


I am working on leetcode problem 206 and have come up with :

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        
        if head:    
            if head.next:

                curr1 = head
                curr2 = head.next
                curr1.next = None

                while curr2:
                
                    #curr1, curr2.next, curr2 = curr2, curr1, curr2.next
                    #curr2.next, curr2, curr1 = curr1, curr2.next, curr2

                    curr1, curr2, curr2.next = curr2, curr2.next, curr1
                    
                return curr1
            
        return head

the code above works in the case of either commented out line but fails due to time for the currently un-commented line in the while loop.

Could anyone explain why this is?

I tried changing the order of the variables that must be changed and that somehow results in a differnet output. Even though the variables are swapping to the same other variables just in a different position.


Solution

  • Yes, the order matters. We can rewrite each of these tuple assignments as separate assignments to clarify this:

    This working one:

    curr1, curr2.next, curr2 = curr2, curr1, curr2.next
    

    ...is equivalent to (ignoring there is a temp name here):

    temp = (curr2, curr1, curr2.next)
    curr1 = temp[0]
    curr2.next = temp[1]
    curr2 = temp[2]
    

    Let's do this breakdown with the non-working assignment:

    curr1, curr2, curr2.next = curr2, curr2.next, curr1
    

    This can be understood as:

    temp = (curr2, curr2.next, curr1)
    curr1 = temp[0]
    curr2 = temp[1]
    curr2.next = temp[2]
    

    Note how the assignment to curr2 impacts what the last assignment will be to. And in this case that is not what you want. You want the "old" curr2 to get its next attribute updated, not the "new" one as is happening here. The assignment to curr2 should happen after curr.next has been updated, and that is the case in the two working versions you provided.