Is there a way to detect the first element of a circular list in Python? In Java and C++ you can just establish a pointer to the first element.
Question I came across: Given a circular linked list, implement an algorithm which returns the node at the beginning of the loop.
A circular linked list has no true beginning & end. But from your comment, I think you want to detect when you reach the element you started with while looping through the list.
#The structure of ListNode
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
# Supposes you have a circular linked list and you have a reference to head. You can do as follows to print the whole list.
current = head.next
while current != head: # stop when it comes back to head
print current.val
current = current.next
I think you need a depth first search to answer this in generality, here's the sort of thing:
a = [1,2,3]
b = [4,5,6]
a[1] = b
b[2] = a
def is_list(l):
try:
it = iter(l)
return l
except TypeError:
return None
def dfs(a, colors):
l = is_list(a)
print 'is_list:', l
if l:
if colors.has_key(id(l)):
print 'cycle detected'
return l
colors[id(l)] = ''
for ll in l:
dfs(ll, colors)
colors = {}
dfs(a, colors)
Related
So I have an assignment that ask me to append a doubly circular linked list to the end of another doubly circular list. For example, I have two doubly circular linked lists which are [0,1,2,3] and [10,11,12,13]. The output should be [0,1,2,3,10,11,12,13], and we also have to make it reversed which is [13,12,11,10,3,2,1,0]
My assignment provides two py files. The first one is called "linked_list.py". It's for creating a doubly circular linked list. I cannot modify this file.
class Node:
def __init__(self, x):
self.data = x
self.next = None
self.pre = None
class DoubleLinkedList:
def __init__(self):
self.head = None
def insertHead(self, x):
self.head = Node(x)
self.head.next = self.head
self.head.pre = self.head
def insert(self, y, x):
tmp = self.head
nodex = Node(x)
while True:
if tmp.data == y:
break
tmp = tmp.next
nodex.next = tmp.next
nodex.pre = tmp
tmp.next.pre = nodex
tmp.next = nodex
def printForward(self):
print("Forward :",end=" ")
tmp = self.head
print(tmp.data,end=" ")
tmp = tmp.next
while tmp!=self.head:
print(tmp.data,end=" ")
tmp=tmp.next
print()
def printBackward(self):
print("Backward :",end=" ")
tmp = self.head.pre
print(tmp.data,end=" ")
tmp = tmp.pre
while tmp!=self.head.pre:
print(tmp.data,end=" ")
tmp=tmp.pre
print()
The second code is "combine.py"
from linked_list import Node, DoubleLinkedList
def combine(l1, l2):
#This is the main part of this assignment, write a function that can combine two doubly circular linked lists.
#There's no need to return value since we directly modify LL1 as our final result
if __name__=="__main__":
LL1 = DoubleLinkedList()
LL1.insertHead(0)
LL1.insert(0, 1)
LL1.insert(1, 2)
LL1.insert(2, 3) #LL1 = [0,1,2,3]
print(LL1)
LL2 = DoubleLinkedList()
LL2.insertHead(10)
LL2.insert(10, 11)
LL2.insert(11, 12)
LL2.insert(12, 13) #LL2 = [10,11,12,13]
print(LL2)
combine(LL1, LL2)
LL1.printForward() # This function can print the combined linked list
LL1.printBackward() # This function can reverse the
# Forward output : 0 1 2 3 10 11 12 13
# Backward output : 13 12 11 10 3 2 1 0
At first I was thinking about using the same method as appending normal linked list but I realized that the last node of circular linked list will point at the first node. Then I got confused by the whole assignment. How can I make one doubly circular linked list get appended to the end of another doubly circular linked list? Some detailed explanations are appreciated. Thanks in advance.
Basically, you will need to append the complete l2 chain between head and head.pre of l1. In order to do so, I see two different methods:
The naive one (complexity: O(n))
Simply reuse the methods that were nicely provided to you. In the end, you are just asked to add multiple values at the end of l1:
def combine(l1, l2):
l1_tail_val = l1.head.pre.data
l2_head = l2.head
l1.insert(l1_tail_val, l2_head.data)
l2_head = l2_head.next
l1_tail_val = l2_head.data
while l2_head != l2.head:
l1.insert(l1_tail_val, l2_head.data)
l1_tail_val = l2_head.data
l2_head = l2_head.next
This method will need to iterate over l2 entirely, so if the list is big, it can take some time.
Edit: This is even worse than that, since in order to find the insert place, the insert method will iterate over l1, always to find that the wanted insert location is at the end. So this is closer to O(n^2) than O(n)
The efficient one (complexity: O(1))
With this one, you don't have to iterate over anything, you just need to connect the nodes so that it forms a single circular list:
def combine(l1, l2):
l1_tail = l1.head.pre
l1_head = l1.head
l2_tail = l2.head.pre
l2_head = l2.head
# Now just update the references
# Then end of l2 should be connected to the head of l1 (same for the reverse relation)
l1_head.pre = l2_tail
l2_tail.next = l1_head
# The start of l2 should be connected to the end of l1 (same for the reverse relation)
l1_tail.next = l2_head
l2_head.pre = l1_tail
This does not rely on any loop or recursion, thus giving you a constant complexity, no matter the lists lengths
I know StackOverflow isn't writing the question and getting the answer site but here is my problem from leetcode.
l1 = input()
l2 = input()
def f(x): #Gives reversed of linkedlist ex. [2, 4, 3] return 342
a, u = 0, 0
for ele in x:
if ele.isnumeric():
a += int(ele)*(10**u)
u += 1
return a
l = list(int(i) for i in str(f(l1) + f(l2)))
print(list(reversed(l)))
This question is leet code problem so here I have solved the problem but this is something different they do not want spaces between the number after comma.
Input: [2,4,3]
[5,6,4]
My output:
[7, 0, 8]
Expected output: [7,0,8]
However, I also tried
k = str(f(l1) + f(l2))
print("[" + ",".join(str(k)[::-1]) + "]")
You aren't supposed to use input() and print() on leetcode
When you start a problem they give you a function you have to fill and return the result.
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
#put your code here
return the_result
This problem is supposed to use a linked list with nodes defined as
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
this is what should be the input of the addTwoNumbers() method you are supposed to code.
But somehow by using input() you are bypassing this and grabbing the raw list.
Also, prints(stdout) are not what is being evaluated by the leetcode system, they look for the output of addTwoNumbers() which in this case is blank.
Here is the complete solution;
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def __init__(self):
self.head = None
def rev(self, ls):
res = []
self.head = ls
while self.head:
res.append(str(self.head.val))
self.head = self.head.next
return list(reversed(res))
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
res1 = int(''.join(self.rev(l1)))
res2 = int(''.join(self.rev(l2)))
res3 = str(res1 + res2)
resls = list(reversed([i for i in res3]))
self.head = ListNode(resls[0], None)
finalres = self.head
for i in range(1, len(resls)):
lsn = ListNode(resls[i], None)
finalres.next = lsn
finalres = finalres.next
return self.head
**Explanation**:
I will asume that you know the basics of linked lists i.e, what are they (in case you have confusion please comment).
So in the Solution class, i simply defined a self.head attribute inside its __init__ method which i am going to use to keep track of elements in a linked list. It is initially set to None as right there we don't have any data there.
Then i defined a rev method to reverse the given linked list.
Inside the rev, i created an empty list res to store the data from the linked lists provided.
Rev also takes a linked list as an argument as i will take the data from it and append it to the res list
So i put self.head equal to that linked list ls provided when we call the method.
Then i simply ran a while loop until self.head is defined (i.e, until it is not None which means there is still data).
After every iteration, i kept changing self.head to self.head.next to move forward in the linked list and grab the data from every node of that linked list and append that to res list.
At the end i simply returned the reversed res.
Then i defined another method, addTwoNumbers which takes two linked lists and returns there sum as per the requirement.
First of all i need those two linked lists to be in integer form and reversed ( as per condition). So i used the rev method to reverse them, join method (inbuilt method in python to join a list of strings) to convert the list to string and then int method to convert the string to int.
I did the same with both of the linked lists and stored them in res1 and res2 respectively.
Then i took their sum (res3) and converted it to string as we cannot iterate over an integer .
Then i converted the res3 to a reversed list .
Now the last step, return the whole thing as a listnode.
So i simply created an instance of ListNode;
self.head = ListNode(resls[0], None)
This will create an instance of ListNode with data as first element of resls and next as none.
Then i stored it inside another variable to refrence to the same instance and don't change it.
Then ran a far loop on the remaining elements and kept adding data and next.
Hope you understood. Thanks.
That is just the default representation of a list, it has a space after each comma
x = [1, 2, 3]
print(x) # [1, 2, 3] type is list
print(str(x).replace(" ", "")) # [1,2,3] type is str
I am writing code to answer the following question: "for two linked lists l1 and l2 that contain positive integers (and have at least one node), return their sum as a linked list. "
For example:
Input: l1 = [7,2,4,3], l2 = [5,6,4]
Output: [7,8,0,7]
The way I am coding this is to reverse both linked lists, then add them (add this is how you would add two numbers)
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1==[0]:
return l2
if l2==[0]:
return l1
#Reversing both linked lists l1 & l2
prev = None
pointer = l1
while pointer:
curr = pointer.next
pointer.next = prev
prev = pointer
pointer = curr
prev2 = None
pointer2 = l2
while pointer2:
curr2 = pointer2.next
pointer2.next = prev2
prev2 = pointer2
pointer2 = curr2
#prev and prev2 are the heads of the reversed linked list(I've tested this)
#Creating a new linked list that is the addition of the two reversed linked list
l3=ListNode(0)
start_l3 = l3
carry = 0
while prev or prev2:
if prev.val + prev2.val >9:
carry =1
else:
carry = 0
s = prev.val + prev2.val + carry
l3.next = ListNode(s)
l3=l3.next
prev=prev.next
prev2=prev2.next
if carry ==1:
l3.next = ListNode(1)
return start_l3.next
When I run this for the input given above, I get a "NoneType object has no attribute val for the line if prev.val + prev2.val >9:
Any ideas why this is? Because when I test prev and prev2; it does seem to return the reversed linked list.
The reason for the error is that you cannot assume that both prev and prev2 are not None. Your while condition only guarantees that at least one of them is not None, but not both. So that means you still need to have a None check inside the body of the loop.
There are also some other issues:
l1==[0]: is not correct. The left side of this comparison is a linked list instance, while the right side is a standard list. These comparisons will always be False, and so you can just omit them
You are adding the carry to the wrong sum. You should add the carry from the previous iteration to the current sum, so things are currently happing in the wrong order.
The resulting list should be reversed. You can do this on the fly by prefixing each node to l3, instead of appending it. This will also make it unnecessary to create a dummy ListNode(0) before the final loop. You can just start with None.
Your code mutates the original input lists. This will be acceptable on code challenge sites, and be efficient, but it is bad practice. The caller should not be unpleasantly surprised that the lists they provide as input have been reversed by a call to this addTwoNumbers function. You can solve this in several ways, but it is probably easiest to reverse them a second time to undo that operation.
To avoid repetition of code, you should create a reverse function
I'll assume that the ListNode constructor can take a second argument for initialising its next reference:
class ListNode:
def __init__(self, val, nxt=None):
self.val = val
self.next = nxt
Then the corrected code could be:
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
def reverse(lst: ListNode):
prev = None
node = lst
while node:
curr = node.next
node.next = prev
prev = node
node = curr
return prev
#Reversing both linked lists l1 & l2
l1 = reverse(l1)
l2 = reverse(l2)
#Creating a new linked list that is the addition of the two reversed linked list
node1 = l1
node2 = l2
l3 = None
carry = 0
while node1 or node2:
added = carry # The carry from the previous iteration should be used
if node1: # You must have this check
added += node1.val
node1 = node1.next
if node2:
added += node2.val
node2 = node2.next
carry = added // 10 # Simpler way to get the carry
l3 = ListNode(added % 10, l3) # Prefix(!) the new node
if carry == 1:
l3 = ListNode(1, l3)
# Restore the input lists:
reverse(l1)
reverse(l2)
return l3
Further remarks
Concerning the prefixing of nodes into the final list l3:
This is the main statement for doing that:
l3 = ListNode(added % 10, l3)
Let's break this down:
The constructor is called with two arguments:
val = added % 10: this is one digit, so in case added is 14, this expression will evaluate to just 4 (the 1 will go to the carry).
nxt = l3: this is the current (incomplete) list. The first time it is None.
The constructor then assigns these values as attributes of the new node that is being initialised:
self.val = val
self.next = nxt
So here we see that the value of nxt, is assigned to the new node's next attribute. As we passed l3 as argument, we are actually doing:
self.next = l3
By that statement we effectively prefix the new node to the list: the new node becomes the first node of the list. Moreover, self acts as the head of that list, which is now one node longer. We want to keep track of this new head, and so we assign the new node back to l3:
l3 = ListNode(added % 10, l3)
As the first time l3 was None, this will just create a one-node list, whose next attribute is that None. But the second time this is executed, we get a new node whose next refers to the "existing" node, so now we have a list of two... etc.
Sometimes it can come in handy to start a linked list with a dummy node like ListNode(0), which then later can be removed. However, in this revised algorithm that would not help, and so we start with None, which after the first iteration of the loop will serve as second argument to the ListNode constructor, which in turn will use it to initialise the next attribute of the new node. This new node will remain the tail of the list as other nodes are prefixed to it.
I have edited the code to incorporate the notes from below (from Trincot), the only thing I am still not clear about is the "l1.next= MergeTwoLists(l1.next,l2)" ; I still don't think this is right- any ideas how to amend this?
Also, do I need a while statement, since the recursive call seems to loop in some sense already.
Input: l1 = [1,2,4], l2 = [1,3,4]
Output: [1,1,2,3,4,4]
def MergeTwoLists(l1,l2):
prehead = ListNode(-1)
pointer_run = prehead
#Base Case
if not l1:
return l2
if not l2:
return l1
#Recurrence Relation
while l1 or l2:
if l1.val < l2.val:
pointer_run.next = l1
l1_temp = l1.val
l1.next= MergeTwoLists(l1.next,l2)
else:
pointer_run.next = l2
l2.next = MergeTwoLists(l1,l2.next)
return prehead.next
I am getting None as the output.
This happens when l2.val == l1.val. This is a case that is not captured by any if in your code, and so prehead.next is executed. But that next attribute never received a value other than the initial value, which I suppose is set to None by the ListNode constructor.
There are the following issues:
The last if should really be an else, as you want to capture the above described case in one of those two blocks. As both these blocks (the if block and now else block) end with a return, there should be no possibility to ever get to return prehead.next: that statement can be removed. That also means that prehead is never read after its next attribute is assigned a value, and therefore serves no purpose.
return MergeTwoLists(l1.next,l2) is not correct. You need to assign the returned value to l1.next. And to avoid that you mutate the input lists, you should first make a new node with the value at l1 and assign to that new node's next attribute. The same is true for the mirrored situation.
The first base case is not necessary, as it is covered by the next.
As ListNode was not given, I add the definition that I will use in the corrected code:
class ListNode:
# Constructor allows caller to optionally provide a next node
def __init__(self, val, nxt=None):
self.val = val
self.next = nxt
# A method to ease the iteration of all list values
def values(self):
yield self.val
if self.next:
yield from self.next.values()
# Define the representation of a list (e.g. for printing)
def __repr__(self):
return " → ".join(map(repr, self.values()))
# A class method to ease the creation of a list
#classmethod
def fromvalues(cls, *values):
head = None
for val in reversed(values):
head = cls(val, head)
return head
Here is the corrected function:
def MergeTwoLists(l1, l2):
if not l1:
return l2
if not l2:
return l1
if l1.val < l2.val:
return ListNode(l1.val, MergeTwoLists(l1.next, l2))
else:
return ListNode(l2.val, MergeTwoLists(l1, l2.next))
Here is how you can run it:
l1 = ListNode.fromvalues(1, 2, 4)
l2 = ListNode.fromvalues(1, 3, 4)
result = MergeTwoLists(l1, l2)
print(result) # 1 → 1 → 2 → 3 → 4 → 4
I'm working through Cracking the Coding Interview 6th ed and am unsure of their definition of 'next'
Their code defining "Linked List" can be found here. I'm trying out the second exercise, which is to find the kth from the end element of a random linked list.
My code:
from LinkedList import LinkedList
def kth_to_last(ll, k):
num_seen = 0
length_list = count_length(ll)
val = ll.head
# ISSUE IS HERE
while val.next != None:
print 'hi'
val.next = val.next.next
"""
while num_seen < (length_list - k):
val = val.next
num_seen += 1
"""
return val.next
# Counts length of LL
def count_length(ll):
val = ll.head
count = 1
while val.next != None:
count += 1
val.next = val.next.next
return count
ll = LinkedList()
ll.generate(10, 0, 99)
print(ll)
kth_to_last(ll, 3)
It's counting through the list just fine, but for the first definition, I can't get it to move through the linked list (it won't print 'hi' at all).
I plan to do something like I have commented out (they also have 'tail' defined so I might try that out), but I'm confused why I can move through the list just fine within 'count_length,' but then I can't seem to move through it within 'kth_to_last'?
Edit: To clarify, if I print val.next within 'kth_to_last' it has a value of 'None'
Edit2:
If I comment out the "count_length," the next proceeds just fine. Could someone explain to me why calling this function alters next. Has it stuck me at the end of the list?
My code:
def kth_to_last(ll, k):
"""
num_seen = 0
length_list = count_length(ll)
"""
# Start at head
val = ll.head
while val.next != None:
print val.next
val = val.next
This prints the list just fine
You should do val = val.next instead of val.next = val.next.next. The way you're doing it, the list will be truncated to a single element when you call count_length. Because you do count_length at the top of kth_to_last, by the time you get around to walking your list (where your 'hi' is), the list has already been reduced to a single node.
Remember, a linked list is a structure where each node's next property is a pointer to the next node. Your code is modifying the value of next, which is changing the structure of your linked list.
When you process a linked list (in count_length, or in kth_to_last), what you want to do is point yourself at each node in turn. You're not trying to modify the nodes themselves, so you won't assign to their value or next attributes. The way to do this is to change what your pointer (val) is pointing at, and the thing that you want it to point at next is the next node along. Therefore:
val = ll.head
while val is not None:
# do something with val here
val = val.next