给定一个链表,形式如L0->L1->L2->L3-> ... ->Ln-1->Ln,要求重新排序成如下形式:L0->Ln->L1->Ln-1->...
如给定链表为1->2->3->4->5->6,则重新排序后的结果为1->6->2->5->3->4。
这里需注意的是,要求的并不是返回一个新链表,而是直接把原链表重新排序,不需返回任何值。
思路:此题过程稍微有点复杂,可以分为以下三步:
1、寻找链表的中点,把链表分为两部分。如上面链表从3->4这个地方分开。
2、把中点后面的部分倒序。如上面链表后半部分倒序为6->5->4。
3、把前半部分跟后半部分重新组合。如上面链表按照两个部分一边一个元素的顺序组合结果为1->6->2->5->3->4,就得到了最终结果。
public void reorderList(ListNode head) {
if(head == null || head.next == null || head.next.next == null)
return;
ListNode fast = head;
ListNode slow = head;
ListNode start = null;
ListNode curr = null;
while(fast.next != null && fast.next.next != null){ //感觉上奇数和偶数个元素需要区分对待,不过最后发现两种情况的过程是一样的
fast = fast.next.next;
slow = slow.next;
}
start = slow.next;
slow = start.next; //这里slow这个指针重复使用了
curr = slow; //用来将后半部分倒序
while(slow != null){ //倒序
slow = slow.next;
curr.next = start;
start = curr;
curr = slow;
}
slow = head; //slow和fast指针再次重复使用于两部分的合并
fast = head.next;
while(start != null){ //两部分重新合并
slow.next = start;
start = start.next;
slow.next.next = fast;
slow = fast;
fast = fast.next;
}
slow.next = null; //slow.next本来是指向自身的
}
为了节省空间,这里的指针重复使用了,不是很直观。为了直观点,可以三部分分别设置相应的指针,并不会多耗费多少空间。