- Reorder List
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.
For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.
my thoughts:
1. split it into odd and even, merge the odd and reversed even lists.
** misread the requirement
1' split it into first and second halves, merge the first and reversed second lists.
DO NOT forget the cut the list.
my solution:
**********108ms
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reorderList(self, head):
"""
:type head: ListNode
:rtype: void Do not return anything, modify head in-place instead.
"""
if not head:
return head
sec = ListNode(0)
p1, p2 = head, head.next
while p2 and p2.next:
p1 = p1.next
p2 = p2.next.next
# cut the first half
temp = p1.next
p1.next = None
p1 = temp
while p1:
temp = sec.next
sec.next = p1
p1 = p1.next
sec.next.next = temp
p1, p2 = head, sec.next
while p2:
t1, t2 = p1.next, p2.next
p1.next = p2
p2.next = t1
p1, p2 = t1, t2
my comments:
from other ppl's solution:
1. Alogrithm Description:
Step 1: Determine whether there is a cycle
1.1) Using a slow pointer that move forward 1 step each time
1.2) Using a fast pointer that move forward 2 steps each time
1.3) If the slow pointer and fast pointer both point to the same location after several moving steps, there is a cycle;
1.4) Otherwise, if (fast->next == NULL || fast->next->next == NULL), there has no cycle.
Step 2: If there is a cycle, return the entry location of the cycle
2.1) L1 is defined as the distance between the head point and entry point
2.2) L2 is defined as the distance between the entry point and the meeting point
2.3) C is defined as the length of the cycle
2.4) n is defined as the travel times of the fast pointer around the cycle When the first encounter of the slow pointer and the fast pointer
According to the definition of L1, L2 and C, we can obtain:
the total distance of the slow pointer traveled when encounter is L1 + L2
the total distance of the fast pointer traveled when encounter is L1 + L2 + n * C
Because the total distance the fast pointer traveled is twice as the slow pointer, Thus:
2 * (L1+L2) = L1 + L2 + n * C => L1 + L2 = n * C => L1 = (n - 1) C + (C - L2)*
It can be concluded that the distance between the head location and entry location is equal to the distance between the meeting location and the entry location along the direction of forward movement.
So, when the slow pointer and the fast pointer encounter in the cycle, we can define a pointer “entry” that point to the head, this “entry” pointer moves one step each time so as the slow pointer. When this “entry” pointer and the slow pointer both point to the same location, this location is the node where the cycle begins.
================================================================
Here is the code:
ListNode *detectCycle(ListNode *head) {
if (head == NULL || head->next == NULL)
return NULL;
ListNode *slow = head;
ListNode *fast = head;
ListNode *entry = head;
while (fast->next && fast->next->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) { // there is a cycle
while(slow != entry) { // found the entry location
slow = slow->next;
entry = entry->next;
}
return entry;
}
}
return NULL; // there has no cycle
}