I'm new to programming, so excuse the possibly stupid question.
I'm doing leetcodes and I got to the linked lists. I think I understand them okay, it's just that I don't know how to test my code/call my function(?)
Problem I'm working on
Here's my code, I know it works since I uploaded it onto leetcode, but I would still like to be able to run it on my machine.
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
I guess I have two different problems:
the "Optional[ListNode]) -> Optional[ListNode]:" part
and the actual calling of the function
Some questions before used the "typing" module functions like "List", so I would simply import them and they wouldn't be a problem. But I'm not really sure what to do here
To check my solutions, I write a short piece of code that I can put example inputs into
Solution = Solution()
print(Solution.middleNode(head = [1,2,3,4,5,6]))
But isn't the "head" there, just a normal list? Do I have to create an extra function separately to create the "links". I've seen the creation of a linked list done by calling a function every time you want to add a new node. So would I use a for loop to add my example case?
well if you looking for internal boilerplate, below is code for that.
here you need to create classes for nodes, linked list and solutions,.
then with the given number, you need to create a linkedlist object.
this above part is done in leetcode by themself and this object is passed to class Solution method middleNode, where OP code run and give result. next once output is got it is compared with existing solution
# Node class for individual nodes
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
# linked list class, to create a linked list of the list nodes
class LinkedList:
def __init__(self):
self.head = None
# adding a node element to linked list
def add(self, node):
if self.head is None:
self.head = node
else:
curr = self.head
while curr.next:
curr = curr.next
curr.next = node
curr = node
# printing element of existing linked list
def print_ll(self):
curr= self.head
while curr:
print(curr.val)
curr= curr.next
# leetcode solution class
class Solution:
def middleNode(self, head) :
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
# value with which we create list nodes
values = [1,2,3,4,5,6,7,8,9,10]
ll = LinkedList() # create a linked list class object
for i in values:
node = ListNode(i) # creating a list node
ll.add(node) # adding list node to linked list
#ll.print_ll() # printing linked list
x = Solution().middleNode(ll.head) # passing linked list object to leetcode solution method and getting result
while x: # printing result
print(x.val)
x=x.next
I think the problem on LeetCode is poorly worded. head = [1,2,3,4,5] is not really a head as it should only refer to the first item in the list - there seems to be a bit of hidden boilerplate code that creates a linked list from input list and an output list from output node.
Here's an example code that works similiar to the LeetCode task.
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
inp = [1,2,3,4,5,6]
next = None
for i in reversed(inp):
next = ListNode(i, next) # next points to head at the end of the loop
res = Solution().middleNode(next)
out = []
while res:
out.append(res)
res = res.next
print([o.val for o in out])
to make your code work on your machine you have to implement a couple of things:
First, for your first answer, you have to implement the class ListNode given at the top of the leetcode-page:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
The you import "Optional" from typing:
from typing import Optional
Then you have the prerequisites for your code.
You have to initialise the class, as you have mentioned. The only problem here is, that your variable has the same name as your class, what could cause trouble later.
To finish, you have to call your function as you already did, with one little difference: This function has to be called with "head" as a variable of type ListNode, not List, and gives you back a variable of the type ListNode.
In a nutshell, this would be my solution (of course you can and as much ListNodes as you want):
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
# Initialise class
s = Solution()
# Defining nodes of the list, assigning always the next node.
seven = ListNode(7)
six = ListNode(6, next=seven)
five = ListNode(5, next=six)
four = ListNode(4, next=five)
three = ListNode(3, next=four)
two = ListNode(2, next=three)
one = ListNode(1, next=two)
# Calling your function (with "one" as your head node of the list)
# NOTE: As this gives you back an attribute of type ListNode, you have to access the "val" attribute of it to print out the value.
print(s.middleNode(one).val)
Related
This problem is from LeetCode
# Definition for singly-linked list.
# class ListNode
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
In my solution, if I do the following, I get an error that a cycle has been found in the ListNode:
elif (l1.val<l2.val):
sol = ListNode
sol.val = l1.val
sol.next = Solution.mergeTwoLists(self, l1.next, l2)
return sol
Alternatively, if I define sol differently - as the following - the solution works:
elif (l1.val<l2.val):
sol = ListNode (val = l1.val)
sol.next = Solution.mergeTwoLists(self, l1.next, l2)
return sol
The difference is in the way that sol is initially defined.
I realize there are many ways to correctly solve this problem. However, I don't understand the fundamental difference between the two pieces of code above, particularly why one creates a cycle and the other doesn't. I would appreciate any insight!
The issue is with this line:
sol = ListNode
You're not creating a new object of type ListNode, but instead creating a reference to the class definition itself. By adding the round brackets ListNode() you're instantiating this object. This let's you then interact with it by calling it's .val and .next properties.
How to initialize head in this implementation of LinkedList in python?
I know a Node class can be defined that will make things easier.But I am trying to do in this way(like in C++).
class LinkedList:
def __init__(self,val=None,next=None):
self.val = val
self.next = next
If you just have this one class, then it actually serves as a Node class, and you lack the container class that would have the head member.
This has as consequence that the program will have to manage the head itself. The variable that will be used to reference a linked list could be that head variable, but that also means an empty list will be represented by None.
For instance:
head = None # Empty list
head = LinkedList(1, head) # Add the first node to it
head = LinkedList(2, head) # Prepend the second node to it
head = LinkedList(3, head) # Prepend the third node to it.
# Print the values in the list:
node = head
while node:
print(node.val, end=" ")
node = node.next
print()
Output will be:
3 2 1
Is it possible to write this single linked list program in the class Node and using all methods of class LinkedList inside that by eliminating the class LinkedList and using only one class for all this ? If it is possible then why we prefer writing this way and why not with a single class ?
Some say we use it to keep a track of head node but I don't get it. We can simply use a head named variable to store the head node and then use it further in other operations. Then why a different class for head node.
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
def deleteNode(self, key):
temp = self.head
if (temp is not None):
if (temp.data == key):
self.head = temp.next
temp = None
return
while(temp is not None):
if temp.data == key:
break
prev = temp
temp = temp.next
if(temp == None):
return
prev.next = temp.next
temp = None
def printList(self):
temp = self.head
while(temp):
print (" %d" %(temp.data)),
temp = temp.next
There are lots and lots of ways to implement the same interface as this LinkedList class.
One of those ways would be to give the LinkedList class data and next fields, where next points to a linked list... but why do you think that is better? The Node class in your example is only used inside a LinkedList. It has no external purpose at all. The author of this LinkedList class made two classes so he could separate the operations applied to nodes from the operations applied to the list as a whole, because that's how he liked to think about it. Whether you think your way is better or worse is a matter of choice...
But here's the real reason why it's better to keep LinkedList separate from nodes:
In real life programming, you will encounter many singly-linked lists. Probably none of these will be instances of any kind of List class. You will just have a bunch of objects that are linked together by some kind of next pointer. You will essentially have only nodes. You will want to perform list operations on those linked nodes without adding list methods to them, because those node objects will have their own distinct purposes -- they are not meant to be lists, and you will not want to make them lists.
So this LinkedList class you have above is teaching you how to perform those list operations on linked objects. You will never write this class in real life, but you will use these techniques many many times.
Below is a code that divides each number of the node by 10. For example, node = 2->3->3, output would be 0.2->0.3->0.3.
However I am confused on why self.head.next gets updated each time given it's cur that receive the change. Suppose a=1,b=2 and we make a(cur)=b(self.head), if we change the value of a to 3, that wouldn't affect b, b is still 2. Therefore I couldn't understand why changing cur would affect self.head.next. Thank you!
class node(object):
def __init__(self,value,next=None):
self.value=value
self.next=next
class linkedlist(object):
def __init__(self):
self.head=None
self.next=None
def test(self,List):
self.head=node(0)
cur=self.head
while List:
s=List.value/10
cur.next=node(s)
cur=cur.next
List=List.next if List else 0
return self.head.next
Suppose below is the input:
a=node(2)
a=node(2,a)
a=node(3,a)
c=linkedlist()
Below is the output:
c.test(a).value=0.3
c.test(a).next.value=0.2
c.test(a).next.next.value=0.2
I am confused on why self.head.next gets updated each time given it's cur that receive the change
That is because, at least in the first iteration of the loop, self.head is cur:
cur=self.head
After that, it builds a new list with updated values, using a "dummy" node as self.head (and thus the first cur) which is then discarded and only it's next is returned. However, I find that code rather confusing and overly complicated (I had a hard time understanding it myself), e.g. the ternary ... if ... else ... in the last line is redundant as List can not be None at that point. Also, there's no need in making that a class, since none of its member attributes are used beyond the scope of a single execution of the method.
Instead, you could use a simple function, e.g. using a loop and modifying the original list, or even simpler, recursively creating a new list:
def div(lst, d=10):
first = lst
while lst:
lst.value /= d
lst = lst.next
return first
def div(lst, d=10):
return node(lst.value / 10, div(lst.next, d)) if lst else None
For easier debugging, you can also add a __repr__ method to your node class:
def __repr__(self):
return "(%r %r)" % (self.value, self.next)
I am often compiling lists one element at a time in python 3; say for instance I am making a list by going through a linked list with first element head:
l = []
while head:
l.append(head.val)
head = head.next
I was wondering what the best practices are. Is there another way of writing this? Could it be possible to describe the list in one line, with something like this instead:
while head:
l = # something creating the list AND appending elements
head = head.next
Even better: do I always have to use a loop to create lists in similar cases, or are there often ways to make the desired list in one line ?
Thanks!
EDIT : a typo in the code !
From an OOP perspective, the best practice is to rely on Python's __iter__ method to cast an iterable to a list.
I am assuming your linked-list class looks a bit like this.
class LinkedList:
def __init__(self, value, nxt=None):
self.value = value
self.next = nxt
To allow iteration on your linked-list, you can define __iter__
class LinkedList:
def __init__(self, value, nxt=None):
self.value = value
self.next = nxt
def __iter__(self):
while self:
yield self.value
self = self.next
You can then let list handle the cast of the LinkedList iterable.
head = LinkedList(1, LinkedList(2, LinkedList(3)))
lst = list(head) # [1, 2, 3]