How to test programs related to linked lists in Python - python

For example, merge 2 sorted linked lists.
I understand the code for solving the problem. However, how to create two linked lists and see the output? I have the same problem with trees. If I know how to test the input, it will be very helpful.
Input: l1 = [1,2,4], l2 = [1,3,4]
Output: [1,1,2,3,4,4]
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:

For testing solutions with linked lists it helps to have functions (or methods) which translate linked lists to lists and vice versa. So define these:
def to_linked_list(iterable):
head = None
for val in reversed(iterable):
head = ListNode(val, head)
return head
def to_native_list(head):
lst = []
while head:
lst.append(head.val)
head = head.next
return lst
Now you can more easily test your solution:
l1 = to_linked_list([1,2,4])
l2 = to_linked_list([1,3,4])
result = Solution().mergeTwoLists(l1, l2)
print(to_native_list(result))

If you're looking for a test case: try something like this
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
l1 = ListNode(1)
l1.next = ListNode(2)
curr = l1.next
curr.next = ListNode(4)
l2 = ListNode(1)
l2.next = ListNode(3)
l2.next.next = ListNode(4)
I'll leave creating the solution list up to you.

Related

Merge two sorted list using orient object programming

I am merge sorted list, I am using the following function:
def mergeTwoLists(list1,list2):
if len(list1)==0:
return list2
elif len(list2)==0:
return list1
elif list1[0]<=list2[0]:
return [list1[0]]+mergeTwoLists(list1[1:],list2)
elif list2[0]<list1[0]:
return [list2[0]]+mergeTwoLists(list1,list2[1:])
mergeTwoLists([3,5,4],[1,3])
However, I notice there is a answer that uses class:
class ListNode:
def __init__(self, val=1, next=None):
self.val = val
self.next = next
class Solution:
def mergeTwoLists1(self, l1, l2):
if l1 is None:
return l2
elif l2 is None:
return l1
elif l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
How can I call the second function? What is the benefit of using it?

How do you populate values into a class in python

I have a code that works for merging 2 linked lists for leetcode. However, upon testing it, I am facing a bottleneck. How do I populate the ListNode with a list? the following outputs just 1 whatever, not the merged linked list.
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def __str__(self):
return str(self.val)
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
place_holder = ListNode()
tmp = place_holder
while list1 and list2:
if list1.val < list2.val:
tmp.next = list1
list1 = list1.next
else:
tmp.next = list2
list2 = list2.next
tmp = tmp.next
if list1 is None:
tmp.next = list2
if list2 is None:
tmp.next = list1
return place_holder.next
#input the two integer lists
l1 = [1, 2, 4]
l2 = [1, 3, 4]
list1 = ListNode(l1[0])
list2 = ListNode(l2[0])
list_result = Solution().mergeTwoLists(list1, list2)
print(list_result)
Fix your __str__ so it prints the whole linked list:
def __str__(self):
s = f"({str(self.val)})"
if self.next:
s += f" -> {self.next}" # be careful not to build any circular lists...
return s
and now you can see the actual result of your merge function:
(1) -> (1)
which is 100% correct (at least for these inputs) because you merged the lists (1) and (1).
Writing a function that lets you turn a list of multiple numbers into a single linked list will make it easier to test this logic with longer inputs. One option would be to just do this in your ListNode constructor:
from typing import List, Optional, Union
class ListNode:
def __init__(self, val: int = 0, *vals: int) -> None:
self.val = val
self.next = ListNode(*vals) if vals else None
def __str__(self) -> str:
s = f"({str(self.val)})"
if self.next:
s += f" -> {self.next}"
return s
Now you can do:
list1 = ListNode(1, 2, 4)
list2 = ListNode(1, 3, 4)
list_result = Solution().mergeTwoLists(list1, list2)
print(list_result) # (1) -> (1) -> (2) -> (3) -> (4) -> (4)
You need a way to convert a regular Python list to a linked list. Your nodes are initialized with one integer each (never mind that it came from l1 and l2), so they can't grow any next elements by themselves. To fix it, add a static method to ListNode that accepts a list:
class ListNode:
#static
def fromList(lst):
if not lst:
return None
return ListNode(lst[0], next=ListNode.fromList(lst[1:]))
This will recursively convert a Python list into a linked list. Then you can initialize your linked lists like this:
list1 = ListNode.fromList(l1)
list2 = (same)
You need to convert your list value into a List value. (I recommend using separate classes for nodes and the list that consists of those nodes.)
class ListNode:
def __init__(self, val, next=None):
self.val = val
self.next = next
def __str__(self):
return str(self.val)
class List:
def __init__(self, values=None):
# Dummy node that is independent of any actual
# data. You can store the length (or really, any
# metadata you like) in the dummy node.
self.head = ListNode(0)
if values is None:
values = []
for x in values:
self.append(x)
def append(self, value):
...
list1 = List(l1)
list2 = List(l2)
You'll need to implement List.append, and possibly some other methods. It's better to do all the pointer wrangling in List itself and to provide methods for mergeTwoLists to construct the resulting List.

linked nodes in while loop. (add two numbers from LeetCode)

Below is the answer to the addTwoNumbers linked node list question on LeetCode.
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
result = ListNode(0)
temp = result
carry = 0
while l1 or l2 or carry:
val1 = (l1.val if l1 else 0)
val2 = (l2.val if l2 else 0)
carry, out = divmod(val1+val2 + carry, 10)
temp.next = ListNode(out)
temp = temp.next
l1 = (l1.next if l1 else None)
l2 = (l2.next if l2 else None)
return result.next
I am struggling to understand how
result = ListNode(0)
temp = result
outside the while loop and
temp.next = ListNode(out)
temp = temp.next
inside the while loop stores the linked nodes.
I feel that the code should leave result.next unchanged, as result is never called in the while loop, but it clearly isn't the case.

How to generate a linked-list from a standard list in Python

As part of a bigger project, I'm trying to generate a linked-list from a standard list. I've already looked through some topics regarding this problem on SO (e.g. here) but most of codes have much different architecture than mine (linked-list is a class itself). Only the last answer was very similar to my solution.
What I try to accomplish here is to create a generator having, among others, a function creating linked-list from a given input (that's why the structure is rigid here). Also I can't touch ListNode class.
I've tried the following code but it returns only single element linked-list with the last element of the list as a node.
I have a feeling I am close but something is missing. I can create helper functions if that's required but ideally, I would like to avoid it. Has anyone any ideas? Where's the mistake?
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Creator:
def populate(self, in_list):
# creating the head node
out_list = ListNode(in_list[0])
curr = out_list
# iterating over input list
for i in in_list[1:]:
curr = curr.next
curr = ListNode(i)
return curr
# Below the manual approach for a list of four elements/nodes
# manual_list = ListNode(1)
# manual_list.next = ListNode(2)
# manual_list.next.next = ListNode(3)
# manual_list.next.next.next = ListNode(4)
inputs = [1,2,3,4]
result = Creator().populate(inputs)
while result:
print(result.val)
result = result.next
Thank you!
You are in the right direction, just take care of the pointer allocation after adding new node, also keep a reference to the first node and return that:
def populate(self, in_list):
# creating the head node
curr = ListNode(in_list[0])
head = curr
# iterating over input list
for i in in_list[1:]:
temp = ListNode(i)
curr.next = temp
curr = temp
return head
Complete code:
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
class Creator:
def populate(self, in_list):
# creating the head node
curr = ListNode(in_list[0])
head = curr
# iterating over input list
for i in in_list[1:]:
temp = ListNode(i)
curr.next = temp
curr = temp
return head
# Below the manual approach for a list of four elements/nodes
# manual_list = ListNode(1)
# manual_list.next = ListNode(2)
# manual_list.next.next = ListNode(3)
# manual_list.next.next.next = ListNode(4)
inputs = [1,2,3,4]
result = Creator().populate(inputs)
while result:
print(result.val)
result = result.next

How to recyle the linked list node immediately after delete it in python

I want to delete a node in linked list and recyle it immediately in Python, but I don't know how to achieve that, here is example code:
# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
# delete node
def delete_node_after(pre_node):
deleted_node = pre_node.next
pre_node.next = pre_node.next.next
del deleted_node # incorrect, it is only delete `deleted_node` reference to l2
def test():
l1 = ListNode(1)
l2 = ListNode(2)
l3 = ListNode(3)
l1.next = l2
l2.next = l3
delete_node_after(l2)
print(l1.next.val)
print(l2.val) # l2 is still here
The reason I want to do this is that this Linked List will have a long lifecyle, and I want release deleted node's memory immediately.
Or I only can wait for Python to auto recycle it by Reference Count after some while?

Categories