题目描述
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You may not modify the values in the list’s nodes, only nodes itself may be changed.
Example 1:
Given 1->2->3->4, reorder it to 1->4->2->3.
Example 2:
Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
Approach1:
class Solution {
//Runtime: 2 ms, faster than 99.31% of Java
//Memory Usage: 39 MB, less than 89.97% of Java
public void reorderList(ListNode head) {
if (head == null || head.next == null)
return;
// step 1. cut the list to two halves
ListNode prev = null, slow = head, fast = head, l1 = head;
while (fast != null && fast.next != null) {
prev = slow; // prev will be the tail of 1st half
slow = slow.next; // slow will be the head of 2nd half
fast = fast.next.next;
}
prev.next = null;
// step 2. reverse the 2nd half
ListNode l2 = reverse(slow);
// step 3. merge the two halves
merge(l1, l2);
}
public ListNode reverse(ListNode head) {
ListNode prev = null, curr = head, next = null;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
void merge(ListNode l1, ListNode l2) {
while (l1 != null) {
//画图会更加清楚易懂
ListNode n1 = l1.next, n2 = l2.next;
//n1 、 n2 分别是l1 、 l2指向的下一个结点
l1.next = l2;
if (n1 == null)
break;
l2.next = n1;
l1 = n1;//进入下一次的迭代
l2 = n2;
}
}
}
另一种形式方便理解:
class Solution {
//Runtime: 2 ms, faster than 99.31% of Java
//Memory Usage: 39 MB, less than 89.97% of Java
public void reorderList(ListNode head) {
if (head == null || head.next == null)
return;
// step 1. cut the list to two halves
ListNode prev = null, slow = head, fast = head, l1 = head;
while (fast != null && fast.next != null) {
prev = slow; // prev will be the tail of 1st half
slow = slow.next; // slow will be the head of 2nd half
fast = fast.next.next;
}
prev.next = null;
// step 2. reverse the 2nd half
ListNode l2 = reverse(slow);
// step 3. merge the two halves
head = merge(l1, l2);
}
public ListNode reverse(ListNode head) {
ListNode prev = null, curr = head, next = null;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
public ListNode merge(ListNode l1, ListNode l2) {
ListNode head = new ListNode(0);
ListNode handler = head;
while(l1 != null){
handler.next = l1;
l1 = l1.next;
handler = handler.next;
handler.next = l2;
l2 = l2.next;
handler = handler.next;
}
if(l2 != null)
handler.next = l2;
return head.next;
}
}
Approach2:
class Solution{
//Runtime: 2 ms, faster than 99.31% of Java
//Memory Usage: 40.3 MB, less than 29.17% of Java
public void reorderList(ListNode head) {
if(head==null||head.next==null) return;
//Find the middle of the list
ListNode p1=head;
ListNode p2=head;
while(p2.next!=null&&p2.next.next!=null){
p1=p1.next;
p2=p2.next.next;
}
//Reverse the half after middle 1->2->3->4->5->6 to 1->2->3->6->5->4
ListNode preMiddle=p1;
ListNode preCurrent=p1.next;
while(preCurrent.next!=null){
ListNode current=preCurrent.next;
preCurrent.next=current.next;
current.next=preMiddle.next;
preMiddle.next=current;
}
//Start reorder one by one 1->2->3->6->5->4 to 1->6->2->5->3->4
p1=head;
p2=preMiddle.next;
while(p1!=preMiddle){
preMiddle.next=p2.next;
p2.next=p1.next;
p1.next=p2;
p1=p2.next;
p2=preMiddle.next;
}
}
}