Reputation: 323
I am now working on the problem of rearranging the linked list. The logic of the code feels right, but I encounter repeating the endless points of the linked list. I am not sure why, but feel more likely there is something wrong with the definition of the linked list. The question is:
Given the head of a Singly LinkedList, write a method to modify the LinkedList such that the nodes from the second half of the LinkedList are inserted alternately to the nodes from the first half in reverse order. So if the LinkedList has nodes 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> null, your method should return 1 -> 6 -> 2 -> 5 -> 3 -> 4 -> null.
Your algorithm should not use any extra space and the input LinkedList should be modified in-place.
Example 1:
Input: 2 -> 4 -> 6 -> 8 -> 10 -> 12 -> null Output: 2 -> 12 -> 4 -> 10 -> 6 -> 8 -> null
Example 2:
Input: 2 -> 4 -> 6 -> 8 -> 10 -> null Output: 2 -> 10 -> 4 -> 8 -> 6 -> null
My approach is:
def rearrange_linkedlist(head):
# find the middle as the separating point
middle = middle_linkedlist(head)
# reverse the second part
second_head = reverse_linkedlist(middle)
while head and second_head:
following_1 = head.next
following_2 = second_head.next
head.next = second_head
second_head.next = following_1
head = following_1
second_head = following_2
def middle_linkedlist(head):
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
def reserve_linkedlist(head):
current = head
previous = None
while current:
following = current.next
current.next = previous
previous = current
current = following
return previous
The set up of the linked list:
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:
print(str(temp.value) + ' ', end='')
temp = temp.next
print()
def main():
head = node(2)
head.next = node(4)
head.next.next = node(6)
head.next.next.next = node(8)
head.next.next.next.next = node(10)
head.next.next.next.next.next = node(12)
rearrange_linkedlist(head)
head.print_list()
main()
And the result is:
2 12 4 10 6 8 8 8
with repeating 8. I am not sure what is wrong with it. Thanks for your help in advance.
Upvotes: 1
Views: 79
Reputation: 22360
It might be beneficial to split up all three steps into different helper functions. I.e., currently, you only have a helper function for finding the middle and reversing a list. You should probably also have one for merging the two lists (this is where the issue is in your current code):
def rearrange_linkedlist(head):
middle = find_middle(head)
reversed_second_half = reverse_list(middle)
merge_two_lists_inplace(head, reversed_second_half)
def find_middle(head):
fast = slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
return slow
def reverse_list(head):
prev, curr = None, head
while curr:
curr.next, prev, curr = prev, curr, curr.next
return prev
def merge_two_lists_inplace(l1, l2):
while l1 and l2 and l2.next:
l1.next, l1 = l2, l1.next
l2.next, l2 = l1, l2.next
The issue with your code is that the end of the first half of the linked list points to the end of the reversed second half. On the final iteration of your merge loop the list looks like this:
2 -> 12 -> 4 -> 10 -> 6 -> 8 -> null
^ ^
head second_head
When you assign second_head.next = following_1
you're really assigning the final node to point to itself. Checking second_head.next
in your loop condition terminates the loop when it's in the above state.
Upvotes: 1