题目描述:
将给定的单链表L: L 0→L 1→…→L n-1→L n,
重新排序为: L 0→L n →L 1→L n-1→L 2→L n-2→…
要求使用原地算法,并且不改变节点的值
例如:
对于给定的单链表{1,2,3,4},将其重新排序为{1,4,2,3}.
解题思路:
1、把链表分成两部分,如1->2->3->4->5->null,分成l1 : 1->2->3->null,和l2 : 4->5->null
2、将第二个链表反转, 所以l2 : 5->4->null
3、将2个链表合并
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public void reorderList(ListNode head) {
//当链表为空,或只有1个2个Node时,不需要反转
if (head == null || head.next == null || head.next.next == null)
return;
ListNode slow = head;
ListNode fast = head;
//最终slow指向的位置是reorder之后的最后一个Node
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
//slow不可能是Null,end2也不会是Null
//end2指向l2的end node
ListNode end2 = slow.next;
//ppre指向要反转的node的前一个node
ListNode ppre = end2;
//p指向要反转的node
ListNode p = ppre.next;
//pnext指向要反转的node的下一个node,也就是下一个要反转的node
ListNode pnext = null;
//p指向null时,反转结束
while(p != null){
pnext = p.next;
p.next = ppre;
ppre = p;
p = pnext;
}
//反转结束,ppre指向l2的start node
ListNode start2 = ppre;
//将两个链表分离,使各自的end node指向null
end2.next = null;
slow.next = null;
//得到了2个链表l1和l2
ListNode l1 = head;
ListNode l2 = start2;
//为连接l1和l2所用,在改变node.next前要记录之前的node.next
ListNode l1next = null;
ListNode l2next = null;
//合并链表
while(l1 != null && l2 != null){
l1next = l1.next;
l2next = l2.next;
l1.next = l2;
l1 = l1next;
l2.next = l1;
l2 = l2next;
}
}
}