To get the output you have listed at the end of your question, you would need to create a linked list. For instance, if you define the following class:
class ListNode:
def __init__(self, val, nxt=None):
self.val = val
self.next = nxt
def __repr__(self):
return f"ListNode{{val: {self.val}, next: {self.next}}}"
And if you then define list1 as follows:
list1 = ListNode(1, ListNode(2, ListNode(4, None)))
Then the "commands" will give the output that you listed.
List to Linked List
If you want to create the above linked list from the list [1,2,4], then use this function:
def createLinkedList(values):
head = None
for val in reversed(values):
head = ListNode(val, head)
return head
Now you can convert a plain list to a linked list as follows:
list1 = createLinkedList([1,2,4])
Linked List to list
If you want to do the opposite, and create a standard list from a linked list, then define this function:
def linkedListIterator(head):
while head:
yield head.val
head = head.next
Now, if you have a linked list, you can pass it to the above function. For instance:
list1 = createLinkedList([1,2,4])
lst = list(linkedListIterator(list1))
lst will be [1,2,4]
To get the output you have listed at the end of your question, you would need to create a linked list. For instance, if you define the following class:
class ListNode:
def __init__(self, val, nxt=None):
self.val = val
self.next = nxt
def __repr__(self):
return f"ListNode{{val: {self.val}, next: {self.next}}}"
And if you then define list1 as follows:
list1 = ListNode(1, ListNode(2, ListNode(4, None)))
Then the "commands" will give the output that you listed.
List to Linked List
If you want to create the above linked list from the list [1,2,4], then use this function:
def createLinkedList(values):
head = None
for val in reversed(values):
head = ListNode(val, head)
return head
Now you can convert a plain list to a linked list as follows:
list1 = createLinkedList([1,2,4])
Linked List to list
If you want to do the opposite, and create a standard list from a linked list, then define this function:
def linkedListIterator(head):
while head:
yield head.val
head = head.next
Now, if you have a linked list, you can pass it to the above function. For instance:
list1 = createLinkedList([1,2,4])
lst = list(linkedListIterator(list1))
lst will be [1,2,4]
As mentioned in the comments, it appears as though you are confusing a list with a singly linked list.
With the list provided you would just iterate with a for loop like this:
list1=[1,2,4]
for L in list1:
print(L)
Which gives the output:
1
2
4
For linked lists, please refer to this: https://www.tutorialspoint.com/python_data_structure/python_linked_lists.htm
Consider the data structure defined like this (which is often used in Leetcode questions):
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next
So, we start by creating a temporary variable curr, letting it equal the head of the linked list. Then, to reach successive nodes, we repeatedly fetch curr.next and reassign that node instance to curr until we get None, which means we've reached the last node.
But can we make use of Python's __next__ magic method to make all this less cumbersome?
I am having some difficulty understanding how linked lists can be created using an iterated loop.
class ListNode(object):
def __init__(self, x):
self.value = x
self.next = None
def LinkedNodeTest(n):
output = ListNode(0)
temp = output
for i in range(1, n+1):
new = ListNode(i)
temp.next = new
temp = new
return outputLinkedNodeTest(n) returns a linked list from 0 to n when it is called.
How is the variable 'output' being updated with the new nodes? I only see it being assigned ListNode(0) at the beginning of the function and it is not getting assigned in the for loop. It looks like assigning 'new' to 'temp' somehow updates 'output'; I don't really understand how that works.
Thanks for the help.
You could do something like this:
def print_linked_list(item):
# base case
if item == None:
return
# lets print the current node
print(item.item)
# print the next nodes
print_linked_list(item.next)
Try this.
class Node:
def __init__(self,val,nxt):
self.val = val
self.nxt = nxt
def reverse(node):
if not node.nxt:
print node.val
return
reverse(node.nxt)
print node.val
n0 = Node(4,None)
n1 = Node(3,n0)
n2 = Node(2,n1)
n3 = Node(1,n2)
reverse(n3)
The short answer to this is that, Python is a pass-by-object-reference language, not pass-by-reference as implied in the question. It means that:
resultandresult_tailare two variables that happen to point at the same value- Mutation / Changing of the underlying value (
result_tail.next = ListNode(1)) will affect the value shown byresult - However, assigning / pointing the variable
result_tailto another value will NOT affect the value ofresult result_tail = result_tail.nextis assigning the next node of the node that is currently assigned by the variable
The following is an visualization of the values that are assigned to the variables (r = result, rt = result_tail):
result = ListNode(0)
#r
#0 -> None
result_tail = result
#r
#0 -> None
#rt
result_tail.next = ListNode(1)
#r
#0 -> 1 -> None
#rt
result_tail = result_tail.next
#r
#0 -> 1 -> None
# rt
result_tail.next = ListNode(2)
#r
#0 -> 1 -> 2 -> None
# rt
result_tail = result_tail.next
#r
#0 -> 1 -> 2 -> None
# rt
References for additional reading:
- An article explaining the Python pass-by-object reference style in detail https://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/
- An answer explaining Python's pass-by-object reference style https://stackoverflow.com/a/33066581/12295149
- Question asking on Python's object reference style Understanding Python's call-by-object style of passing function arguments
For those reading this in the future: I wanted to debug linked list problems on a local environment so here is what I did.
- Modified the Leetcode code for ListNode by including the dunder "repr" method. This is for when you want to print a ListNode to see what its value and next node(s).
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def __repr__(self):
return "ListNode(val=" + str(self.val) + ", next={" + str(self.next) + "})"
- Next, I made a recursive function that makes a nested ListNode when you pass in a list. This is so you can test your methods by passing in lists (instead of having to manually make a confusing looking ListNode yourself.
def list_to_LL(arr):
if len(arr) < 1:
return None
if len(arr) == 1:
return ListNode(arr[0])
return ListNode(arr[0], next=list_to_LL(arr[1:]))
- Here is an example that tests my answer for the "reverseList" problem:
def reverseList(head: ListNode) -> ListNode:
prev = None
while head:
next_node = head.next
head.next = prev
prev = head
head = next_node
return prev
# test cases
t1 = list_to_LL([1, 2, 3, 4, 5]) #ListNode(val=1, next={ListNode(val=2, next={ListNode(val=3, next={ListNode(val=4, next={ListNode(val=5, next={None})})})})})
t2 = list_to_LL([1, 2]) #ListNode(val=1, next={ListNode(val=2, next={None})})
t3 = list_to_LL([])
# answers
print(reverseList(t1))
print(reverseList(t2))
print(reverseList(t3))
If readability is a concern, why use single-character variable names? Replace them with something a bit more meaningful: v -> value, n -> next_, etc.
If you followed Python's data model your class could be used more easily and conventionally. For example, implementing size as a method seems a bit odd - if you called it __len__, then it would behave correctly with len and in a boolean context. Looking at the documentation for other, similar data structures can help with picking sensible names (I would expect an insert to take an index, for example, like the other sequences); in your case, maybe start with the deque's interface.
If you follow the conventional implementation, any of the following should work in a predictable way:
if thing in linked_list:for thing in linked_list:list(linked_list)(which would really simplify your__str__implementation)if linked_list:
You could also leverage Python's abstract base classes; if you inherit from Sequence and implement the required methods, for example, you get some additional behaviour for free.
In general you're following the style guide, but Node as a temporary variable name sticks out. It shadows the class you just instantiated and naming a variable in CamelCase is not the convention, it should be snake_case. In fact, it's entirely pointless; why not just self.node = Node(v, self.head)?
To make @jonrsharpe's suggestion more specific, this is one way to implement __iter__, without having to add another iterator class. It also gives you the __str__ method for free.
def __iter__(self):
"""
Iterate over the linked list.
"""
current = self.head
while current is not None:
yield current.value
current = current.next
def __str__(self):
"""
Prints the current list in the form of a Python list
"""
return str(list(self))
Here is an example of its usage:
>>> l = LinkedList()
>>> l.insert(1)
>>> l.insert(2)
>>> for x in l:
... print x
...
2
1
>>> list(l)
[2, 1]
>>> print(l)
[2, 1]
Note that I used is not None instead of != None, read the answers here, if you want to know why.
No, but you can use a list:
def make_nodes(n):
nodes = []
nodes.append(Node(0,None)) # head node
for i in range(1, n):
nodes.append(Node(i, None))
nodes[i-1].next = nodes[i] #somehow link them
return nodes
nodes = make_nodes()
head = nodes[0]
second = nodes[1]
last = nodes[-1]
You could also use a dictionary, and use the node number as the key. But a list seems more natural in this case.
But why would you want to do this? You might as well just use a Python list of Nodes. Creating the node list can be easily done with a list comprehension. Iterating over the list could then be done with a simple for loop:
nodes = [Node(i) for i in range(n)]
for node in nodes:
print(node.payload)
You can use dictionaries and/or list to do what you are trying to achieve there.
But still if you are trying to test some data structure(s) for learning purpose you can create a class Node and work on it.
class Node(object):
__data = None
__ref_to_next = None
def __init__(self, d):
self.set_data(d)
def set_data(self, d):
self.__data = d
def set_ref_to_next(self, r):
self.__ref_to_next = r
def append_a_node(self, new_node):
cnode = self
while cnode.__ref_to_next != None:
cnode = cnode.__ref_to_next
cnode.set_ref_to_next(new_node)
def traverse(self):
cnode = self
while cnode.__ref_to_next != None:
print cnode.__data
cnode = cnode.__ref_to_next
def make_nodes(n):
head_node = Node(0)
for i in range(1,n):
new_node = Node(i)
head_node.append_a_node(new_node)
You can use the append function to populate the linked list simulation.
The question doesn't require you to use regular lists. Since the lists are stored in "reverse order", that actually helps because you would add digits individually between both lists, then calculate/carry overflows moving left-to-right. For example, adding linkedlists [5, 1] + [5] would cause you to add one node to the resulting list [0, , then you iterate to the next position, carrying forward the 10s digit, then do 1 from your input plus 1 from the carry of the previous iteration, getting 2 , so the result is [0, 2]. If you carry a 1 into a 9, then you bring the carry digit forward again
Besides, if you're going to build a regular list, you might as well convert to an int, instead, do the math, then turn the int into the linked list...
But to convert a LinkedList into a regular list, without that LinkedList class being an iterable type itself, would look like this
ll = ListNode(...)
l = []
n = ll
while n is not None:
l.append(n.val)
n = n.next
Otherwise, if it were a proper Python iterable type, [n.val for n in ll]
You can patch iterability into those linked lists with this:
def ll_iter(node):
while node:
yield node.val
node = node.next
ListNode.__iter__ = ll_iter
Then in your code you can just do:
l1 = list(l1)
But I think it's simplest to just write a recursive solution working with the linked lists directly. You don't even get recursion depth problems, as the lists are guaranteed to have at most 100 nodes.