I have to reverse a sub list in my linked list and then return the original linked list but with the sublist reversed. The question is as follows...
Given the head of a LinkedList and two positions ‘p’ and ‘q’, reverse the LinkedList from position ‘p’ to ‘q’.
For example
1 -> 2 -> 3 -> 4 -> 5 -> null, p = 2, q = 4 then,
1 -> 4 -> 3 -> 2 -> 5 -> null
from __future__ import print_function
class Node:
def __init__(self, value, next=None):
self.value = value
self.next = next
def print_list(self):
temp = self
while temp is not None:
print(temp.value, end=" ")
temp = temp.next
print()
def reverse_sub_list(head, p, q):
start, end = head, head
previous = None
while p > 1:
previous = start
start = start.next
p -= 1
while q > 0:
end = end.next
q -= 1
last_node_of_sub_list = start
sub_list = reverse(start, end)
previous.next = sub_list
last_node_of_sub_list.next = end
return head
'''
first_list = head
last_list = end
while first_list is not None:
first_list = first_list.next
first_list = sub_list
while sub_list is not None:
sub_list = sub_list.next
sub_list = last_list
return head
'''
def reverse(head, last_node):
previous = None
while head is not last_node:
_next = head.next
head.next = previous
previous = head
head = _next
return previous
def main():
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
head.next.next.next = Node(4)
head.next.next.next.next = Node(5)
print("Nodes of original LinkedList are: ", end='')
head.print_list()
result = reverse_sub_list(head, 2, 4)
print("Nodes of reversed LinkedList are: ", end='')
result.print_list()
main()
In my while loops I thought I was connecting the last node of the first_list to sub_list and the last node of sub_list to the last_list.
Turns out that when I return head, head is now only 1 -> 2 -> null
This happens when I reverse the sub_list which is fine and I understand that part, but I thought I was reconnecting my lists again.
def reverse_sub_list(head, p, q):
start, end = head, head
previous = None
while p > 1:
previous = start
start = start.next
p -= 1
Now before moving with q > 0 while loop, you can just store the values of the previous and current and continue with q > 0 while loop.
And inside this loop, the reverse is done and q is decremented
connection = previous
tail = current
while q > 0:
currentNext = current.next
current.next = previous
previous = current
current = currentNext
q--
Now all we have got is whether connection was null or not. If the connection is null, then you can set previous to head else set previous to connection.next
if connection != None:
connection.next = previous
else:
head = previous
tail.next = current
return head
Full Code :
def reverse_sub_list(head, p, q):
current = head
previous = None
while p > 1:
previous = start
current = current.next
p -= 1
connection = previous
tail = current
while q > 0:
currentNext = current.next
current.next = previous
previous = current
current = currentNext
q--
if connection != None:
connection.next = previous
else:
head = previous
tail.next = current
return head
You can check this link for more explanation and figure : Click here
https://leetcode.com/problems/reverse-linked-list-ii/description/
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
if left == right:
return head
prev = start = prev_start = None
node = head
for count in range(1, right + 1):
if count >= left:
if not start:
prev_start = prev
start = node
nxt = node.next
node.next = prev
prev = node
node = nxt
else:
prev = node
node = node.next
if prev_start:
prev_start.next = prev
if start:
start.next = node
return head if left > 1 else prev
Related
I am trying to remove the kth element from the END of a linked list. Here is my code
class LinkedList:
def __init__(self, value):
self.value = value
self.next = None
def removeKthNodeFromEnd(head, k):
if k == 0 or head is None:
return
temp = head
while temp is not None and k > 1:
temp = temp.next
k -= 1
if temp is None or k > 1:
return head
trailing = None
leading = head
while temp.next is not None:
trailing = leading
leading = leading.next
temp = temp.next
if trailing is None:
head = head.next
else:
trailing.next = leading.next
head = LinkedList(0)
head.next = LinkedList(1)
head.next.next = LinkedList(2)
head.next.next.next = LinkedList(3)
head.next.next.next.next = LinkedList(4)
head.next.next.next.next.next = LinkedList(5)
head.next.next.next.next.next.next = LinkedList(6)
head.next.next.next.next.next.next.next = LinkedList(7)
head.next.next.next.next.next.next.next.next = LinkedList(8)
head.next.next.next.next.next.next.next.next.next = LinkedList(9)
removeKthNodeFromEnd(head, 10)
while head is not None:
print(head.value)
head = head.next
But this does not work and prints out all the values in the linked list from 0 to 9. Why is this the case? If the node to delete is the head node which I check by checking trailing is None, then I update head = head.next. I am changing head to be the next node. I can return head after this update and the result of head = removeKthNodeFromEnd(head, k) will give me the desired output but why can't I do it the other way without returning anything? For instance in my solution I can get rid of any element in between the first and last node including the last and works just fine. The original head gets updated and node gets removed. But when trying to update the head node head = head.next it does not work.
One way I achieved this is by doing the following...
if trailing is None:
head.value = head.next.value
head.next = head.next.next
But why must I use the values? To me this seems the same as
if trailing is None:
head = head.next
head.next = head.next.next
but does not work
It doesn't work because head in that function is a local name. Assigning to a local variable never does anything to other variables, even not when they happen to have the same name (like the global head).
The "trick" you have by moving a linked list value with head.value = head.next.value will not work when the list only has one node.
One way to do this, is to return the (potentially modified) value of head, and expect the caller to assign this back to their own head variable.
So:
in removeKthNodeFromEnd make sure all return statements are like return head, and that you add a return head at the very end. In short, removeKthNodeFromEnd should always return head.
in the main program, change the call to head = removeKthNodeFromEnd(head, 10)
That will solve your issue.
Here are some ideas to make your code more elegant:
Create a separate class for maintaining the head of the linked list
Improve the constructor, so that it is easier to initialise a linked list
Add an iterator so it is easier to print a linked list
class Node: # renamed
def __init__(self, value, nxt=None):
self.value = value
self.next = nxt # is now an argument
class LinkedList: # added
def __init__(self, *values):
self.head = None
if values: # populate the list with values
for value in reversed(values):
self.push_front(value)
def push_front(self, value):
self.head = Node(value, self.head)
def __iter__(self):
node = self.head
while node:
yield node.value
node = node.next
def removeKthNodeFromEnd(self, k):
if k <= 0:
return
temp = self.head
for _ in range(k):
if not temp: # k is out of range
return
temp = temp.next
if temp:
trailing = self.head
while temp.next:
trailing = trailing.next
temp = temp.next
trailing.next = trailing.next.next
else:
self.head = self.head.next
lst = LinkedList(*range(10))
print(*lst)
lst.removeKthNodeFromEnd(0)
print(*lst)
And if you maintain a size attribute, you can do:
class LinkedList: # added
def __init__(self, *values):
self.head = None
self.size = 0
if values:
for value in reversed(values):
self.push_front(value)
def push_front(self, value):
self.head = Node(value, self.head)
self.size += 1
def __iter__(self):
node = self.head
while node:
yield node.value
node = node.next
def removeAt(self, k):
if 1 < k <= self.size:
trailing = self.head
for _ in range(k - 2):
trailing = trailing.next
trailing.next = trailing.next.next
elif 1 == k <= self.size:
self.head = self.head.next
def removeKthNodeFromEnd(self, k):
self.removeAt(self.size + 1 - k)
Any idea why the summation is returning zero , currently trying to add linked list sum , in leetcode its working fine , however while trying for complete solution it's creating error
Problem from leetcode -
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
Added couple of examples -
Input: l1 = [2,4,3], l2 = [5,6,4]
Output: [7,0,8]
Explanation: 342 + 465 = 807.
Input: l1 = [0], l2 = [0]
Output: [0]
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
class Node:
def __init__(self , data=0,next=None):
self.data=data
self.next=next
class solution:
def __init__(self) -> None:
self.head = None
def insert_at_begining (self,data):
node = Node(data,self.head)
self.head = node
def print(self):
if self.head is None:
print ("Linked list is empty")
return
listr = ''
itr = self.head
while itr:
listr += str(itr.data) + "-->"
itr = itr.next
print (listr)
def revereList(self):
prev , curr = None , self.head
while curr:
tmp =curr.next
curr.next = prev
prev = curr
curr = tmp
self.head= prev
def merge_sorted_upd(self, llist):
p = self.head
q = llist.head
dummy = Node()
tail = dummy
while p and q:
if p.data <= q.data:
tail.next = p
p = p.next
else:
tail.next = q
q = q.next
tail = tail.next
if p:
tail.next = p
if q:
tail.next = q
return dummy.next
def lp_add_two_numbers(self,p,q):
##first create a dummy node
prev=None
dummy = Node()
cur=dummy
carry = 0
l1 = p.head
l2 = q.head
while l1 or l2 :
v1 = l1.data if l1 else 0
v2 = l2.data if l2 else 0
val = v1 + v2 + carry
val = val % 10
carry = val/10
cur.next = Node(val)
if self.head is None:
self.head = cur
else:
dummy.next = cur
dummy=cur
cur = cur.next
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
return dummy.next
if __name__=='__main__':
l1=solution()
l1.insert_at_begining(4)
l1.insert_at_begining(2)
l1.insert_at_begining(1)
l1.print()
l2=solution()
l2.insert_at_begining(7)
l2.insert_at_begining(6)
l2.insert_at_begining(5)
l2.print()
# l1.merge_sorted_upd(l2)
# l1.print()
res=solution()
res.lp_add_two_numbers(l1 , l2)
res.print()
output coming as
1-->2-->4-->
5-->6-->7-->
0 6 8.6 1.8599999999999994
class Node:
def __init__(self, data = None, next = None):
self.data = data
self.next = next
class LinkedList:
def __init__(self, node = None):
self.head = node
self.length = 0
def InsertNode(self, data):
newNode = Node()
newNode.data = data
if self.length == 0:
self.head = newNode
else:
newNode.next = self.head
self.head = newNode
self.length += 1
def printList(self):
temp = self.head
while temp != None:
print(temp.data, end = " ")
temp = temp.next
class AddingListNumbers:
def addTwoNumbers(self, list1, list2):
if list1 == None:
return list2
if list2 == None:
return list1
len1 = len2 = 0
head = list1.head
while head != None:
len1 += 1
head = head.next
head = list2.head
while head != None:
len2 += 1
head = head.next
if len1 > len2:
shorter = list2
longer = list1
else:
shorter = list1
longer = list2
sum = None
carry = 0
while shorter != None:
value = shorter.data + longer.data + carry
carry = value / 10
value -= carry * 10
if sum == None:
sum = Node(value)
result = sum
else:
sum.next = Node(value)
sum = sum.next
shorter = shorter.next
longer = longer.next
while longer != None:
value = longer.data + carry
carry = value / 10
value -= carry * 10
sum.next = Node(value)
sum = sum.next
longer = longer.next
if carry != 0:
sum.next = Node(carry)
return result
linkedlist = LinkedList()
linkedlist.InsertNode(19)
linkedlist.InsertNode(14)
linkedlist.InsertNode(11)
linkedlist.InsertNode(9)
linkedlist.InsertNode(6)
linkedlist.InsertNode(5)
linkedlist2 = LinkedList()
linkedlist2.InsertNode(17)
linkedlist2.InsertNode(16)
linkedlist2.InsertNode(13)
linkedlist2.InsertNode(6)
linkedlist2.InsertNode(2)
linkedlist2.InsertNode(1)
linkedlist2.InsertNode(24)
linkedlist2.InsertNode(3)
linkedlist2.InsertNode(11)
list3 = LinkedList()
ResultList = AddingListNumbers()
list3.next = ResultList.addTwoNumbers(linkedlist, linkedlist2)
list3.printList()
I have created Node and LinkedList classes and then another class AddingListNumbers for adding the list number.
I am getting an error message:
value = shorter.data + longer.data + carry
AttributeError: 'LinkedList' object has no attribute 'data'
I don't understand how to debug this one. How to handle attribute errors?
Below is the image of the error message.
The issue is with this section:
if len1 > len2:
shorter = list2 # should be list2.head instead
longer = list1 # should be list1.head instead
else:
shorter = list1 # should be list1.head instead
longer = list2 # should be list2.head instead
With that said, however, this code can be optimised to traverse the lists only once. In this implementation you're first finding the shorter list and then adding while the shorter list is traversed. It can be done in single traversal as:
Repeat these steps while list1 is traversed OR list2 is traversed completely
Add data from node of list1, if it exists, or add 0
Add data from node of list2, if it exists, or add 0
Add carry to the above sum.
Calculate divmod of the sum and re-assign carry and sum.
Move pointers ahead, if next nodes are present.
The resultant list will have sum of the lists.
I couldn't find a simple implementation of Merge Sort in Python for Linked Lists anywhere. Here's what I tried:
Definition for singly-linked list:
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
Merge Sort Implementation:
def mergeSortLinkedList(A):
# Base case length of 0 or 1:
if A == None or A.next == None:
return A
leftHalf, rightHalf = splitTheList(A)
mergeSortLinkedList(leftHalf)
mergeSortLinkedList(rightHalf)
# The above two lines should be modified to the following. Thanks to the answers.
# leftHalf = mergeSortLinkedList(leftHalf)
# rightHalf = mergeSortLinkedList(rightHalf)
return mergeTheLists(leftHalf, rightHalf)
Split:
def splitTheList(sourceList):
if sourceList == None or sourceList.next == None:
leftHalf = sourceList
rightHalf = None
return leftHalf, rightHalf
else:
midPointer = sourceList
frontRunner = sourceList.next
# totalLength += 1 - This is unnecessary
while frontRunner != None:
frontRunner = frontRunner.next
if frontRunner != None:
frontRunner = frontRunner.next
midPointer = midPointer.next
leftHalf = sourceList
rightHalf = midPointer.next
midPointer.next = None
return leftHalf, rightHalf
Merge:
def mergeTheLists(leftHalf, rightHalf):
fake_head = ListNode(None)
curr = fake_head
while leftHalf and rightHalf:
if leftHalf.val < rightHalf.val:
curr.next = leftHalf
leftHalf = leftHalf.next
else:
curr.next = rightHalf
rightHalf = rightHalf.next
curr = curr.next
if leftHalf == None:
curr.next = rightHalf
elif rightHalf == None:
curr.next = leftHalf
return fake_head.next
Data:
# Node A:
nodeA1 = ListNode(2)
nodeA2 = ListNode(1)
nodeA1.next = nodeA2
nodeA3 = ListNode(9)
nodeA2.next = nodeA3
nodeA4 = ListNode(3)
nodeA3.next = nodeA4
# Node C:
nodeC1 = ListNode(5)
nodeA4.next = nodeC1
nodeC2 = ListNode(6)
nodeC1.next = nodeC2
nodeC3 = ListNode(4)
nodeC2.next = nodeC3
nodeC4 = ListNode(5)
nodeC3.next = nodeC4
Expected output when mergeSortLinkedList(nodeA1) is called:
1 2 3 4 5 5 6 9
I get the following instead:
2 5 6 9
I am unable to figure out where the miss is. Please help.
You don't use the return values from the recursive call. The code should be:
def mergeSortLinkedList(A):
if A is None or A.next is None:
return A
leftHalf, rightHalf = splitTheList(A)
left = mergeSortLinkedList(leftHalf)
right = mergeSortLinkedList(rightHalf)
return mergeTheLists(left, right)
After the call of the function, the argument in some cases doesn't point to the head of the sorted list.
The next bug in the code is usage of undefined variable totalLength.
Hello I need help trying to figure out these three functions. I am very new to python.
Assignment:
createList(srcSeq) - creates a linked list from the values
contained in the srcSeq sequence structure and returns the head
reference of the new linked list. The values will be added one at a
time by prepending them to the linked list. myValues = [5, 12, 82,
32, 20] myList = createList(myValues)
size(theList) - given the
head reference (theList), returns the number of elements in the
linked list.
printList(theList) - given the head reference
(theList), prints the values in the linked list from front to back
all on one line with the values separated by commas.
valueAt(theList, index) - returns the value contained in the node at
the given index position where the first value is at position 0, the
second at position 1 and so on. If index is out of range, return
None.
append(theList, value) - appends a new value to the end of
the linked list. Assume the list contains at least one node.
concat(listA, listB) - joins or concatenates two linked lists by
linking the last node of listA to the first node of listB.
split(theList) - given the head reference (theList), splits the
linked list in half to create two smaller linked lists. The head
reference of the linked list created from the second half of the list
is returned. Assume the list contains at least one node. If there is
an odd number of nodes in the linked list, the extra node can be
placed in either of the two new lists.
For the append, concat, do I simply just do. I do not know how to do the split method:
def append (theList, value):
current = self.head
while current.self.next != None:
current = self.next
current.newnode
def concat(listA, listB):
if listA.tail == None:
listA.head = listB.head
else:
listA.tail.next = listB.head
elif listB.head != None:
listA.tail = listB.tail
My Entire Code:
def createList( self ):
self.head = None
temp = ListNode( value )
self.next = newnext
temp.self.next(self.head)
self.head = temp
return self.head
def size( theList ):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.self.next
return count
def printList( theList ):
node = self.head
while node:
print self.value
node = self.next
def valueAt( theList, index ):
current = head
count = 0
while current != None:
if count == index:
return current
def append( theList, value ):
current = self.head
while current.self.next != None:
current = self.next
current.newnode
def concat( listA, listB ):
if listA.tail == None:
listA.head = listB.head
else:
listA.tail.next = listB.head
elif listB.head != None:
listA.tail = listB.tail
def split( theList ):
pass
I think you problem is under-specified. but with what we have :
Splitting a singly linked list:
def split( head ):
middle = head
current = head
index = 0
while current.next != None:
if index % 2:
middle = middle.next
current = current.next
index += 1
result = middle.next
middle.next = None
return result
But to be honest, there is a lot more wrong with what you have so far.
If those lists were Python lists the solution would be really simple:
def split(a):
return a[:len(a)/2], a[len(a)/2:]
And now some explanation :) :
The function returns a tuple of two lists, where each list is one half of the supplied list a.
What I use above is called slicing and you can think of the colon character as of the word until. You can supply two _arguments beginning and end separated by that semicolon.
Example time!
a = [1,2,3,4,5]
a[:2] == [1,2]
a[2:] == [3,4,5]
a[1:3] == [2,3,4]
a[2,-2] == [3]
a[-3,-2] == [3,4]
Isn't slicing great? And it comes for free! One extra trick, if you want to make a copy of a list you can do that with slicing too!
b = a[:]
Boom, done! :)
There is more to slicing, you can have two colons, but that's a story for another time.
PS:
Out of curiosity I did your homework :)
class Node:
def __init__(self, data):
self.data = data
self.next = None
def __str__(self, *args, **kwargs):
return str(self.data)
def create_list(iterable):
next_node = current_node = None
for item in iterable:
current_node = Node(item)
current_node.next = next_node
next_node = current_node
return current_node
def size(head):
count = 0
while head:
head = head.next
count += 1
return count
def print_list(head):
while head:
print(head, end="")
if head.next:
print(" > ", end="")
head = head.next
print(flush=True)
pass
def value_at(head, index):
while (head):
if index < 1:
return head
index -= 1
head = head.next
return None
def append(head, value):
while head:
if not head.next:
head.next = Node(value)
return
head = head.next
def concat(headA, headB):
while headA:
if not headA.next:
headA.next = headB
return
headA = headA.next
def split(head):
center = head
index = 0
while head:
if index % 2:
center = center.next
head = head.next
index += 1
headB = center.next
center.next = None
return headB
def main():
a = create_list([1, 2, 3, 4, 5, 6, 7, 8, 9])
print("Print list::")
print_list(a)
print("\nSize:")
print(size(a))
print("\nValue at:")
print("a[-1]: %d" % value_at(a, -1).data)
print("a[0]: %d" % value_at(a, 0).data)
print("a[1]: %d" % value_at(a, 1).data)
print("a[5]: %d" % value_at(a, 5).data)
print("a[8]: %d" % value_at(a, 8).data)
# print("value # 9 %d"% value_at(my_head,9).data)
print("\nAppend (10):")
print_list(a)
append(a, 10)
print_list(a)
print("\nConcat a, b:")
print_list(a)
b = create_list([11, 12, 13])
print_list(b)
concat(a, b)
print_list(a)
print("\nSplit:")
print_list(a)
print("..into..")
b = split(a)
print_list(a)
print("Size a: %d" % size(a))
print_list(b)
print("Size b: %d" % size(b))
if __name__ == "__main__":
main()