思路就是:
1 用快慢指针找到中间节点
2 翻转中间节点后一个元素到最后一个元素区间的所有元素
3 断开前半段和翻转后的后半段元素
4 把前半段和翻转后的后半段元素以交叉的方式合并起来
5 特殊处理输入为空,只有一个元素和只有两个元素的corner case,就是多加几个if...return
感想:可以看出翻转链表实在是非常重要,是做很多题目的基础。还有merge的思想也很重要!
package Level4;
import Utility.ListNode;
/**
*
* 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}.
*
*/
public class S143 {
public static void main(String[] args) {
int[] list = {1};
ListNode head = ListNode.create(list);
reorderList(head);
}
public static void reorderList(ListNode head) {
ListNode fast = head;
ListNode slow = head;
// 找到中间节点
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
}
//System.out.println(slow.val);
ListNode preReverse = slow; // preReverse不用翻转,因为它永远在最后一个
if(preReverse == null){
return;
}
// 翻转后半段
ListNode reHead = preReverse.next;
if(reHead == null){
return;
}
ListNode preCur = reHead.next;
ListNode cur = reHead.next;
reHead.next = null;
while(cur != null){
cur = cur.next;
preCur.next = reHead;
reHead = preCur;
preCur = cur;
}
preReverse.next = reHead;
//head.print();
// 交叉合并两个链表
preReverse.next = null; // 断开前半段和翻转后的后半段元素
cur = head;
while(reHead != null && cur!=null){
ListNode tmp = cur.next;
cur.next = reHead;
reHead = reHead.next;
cur.next.next = tmp;
cur = tmp;
tmp = cur.next;
}
//head.print();
}
}