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}
.
题解:对于一个链表L,L0→L1→…→Ln-1→Ln,对它进行重新排序,重新排序后的结果为L0→Ln→L1→Ln-1→L2→Ln-2→…,即最后一个插在第一个后面,倒数第二个插在第二个后面,倒数第三个插在第三个后面,。。。。 注意题目有个要求,你不能通过替换链表节点值的方式解决此问题
分析:我想有些人对这个问题应该比较熟悉,对于一个链表L,L0→L1→…→Ln-1→Ln,对它进行重新排序,排序后的结果
为L0→L(n/2+1)→L1→L(n/2+2)→L2→L(n/2+3)→…,即链表分为两部分,左边的长度-右边的长度<=1(链表长度偶数时,左右相等,奇数时左边多一个节
点)。右边第一个插在左边第一个后面,右边第二个插在左边第二个后面,右边第三个,插在左边第三个后面。。。
For example,
Given{1,2,3,4},reorder it to{1,3,2,4}
显然,解决这个问题分为两步
第一步,找到链表的中间位置
第二步,将右半部分插入左半部分
但是这个LeetCode问题中,对右半部分的插入顺序刚好与上述问题的插入顺序逆序,我们很自然的可以想到,在执行插入操作之前,应该有一个逆序操作,所以解决这个问题就分为了三步。
第一步,找到链表的中间位置
第二步,将右半部份做逆序调整
第三部,将右半部份插入到左半部分
以下是代码:
public void reorderList(ListNode head) {
if(head==null||head.next==null) return;
//第一步,找到链表中间位置
ListNode p1=head;
ListNode p2=head;
while(p2.next!=null&&p2.next.next!=null){
p1=p1.next;
p2=p2.next.next;
}
//对右半部份执行逆序操作 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;
}
//将右半部份插入到左半部分 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;
}
}
对三步中所涉及的指针操作的解析