题目:
给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
给定链表 1->2->3->4, 重新排列为 1->4->2->3.
来源:力扣(LeetCode)
解:
这道题显然就是首尾不断重连接,1-n-2-(n-1)-3......-中点。
这道题最简单的就是直接首尾重连接,但是每次获取尾部都要遍历一遍,时间上达到了O(n^2)。如果建立数组重连的话,辅助空间O(n)。
这里采用分割为首尾两部分,尾部倒序,再重连接。代码多,但是时间为O(n),空间O(1)。
class Solution {
public void reorderList(ListNode head) {
if(head==null || head.next==null){
return;
}
ListNode lo=head,fs=head.next;
//快慢指针找中点,偶数刚好两个新链一样长,奇数的话2链长一个
while(fs.next!=null){
if(fs.next.next==null){
fs=fs.next;
break;
}else{
fs=fs.next.next;
}
lo=lo.next;
}
//翻转后半部分
ListNode t1=lo.next,t2=t1.next,tt;
lo.next=null;
t1.next=null;
while(t2!=null){
tt=t2;
t2=t2.next;
tt.next=t1;
t1=tt;
}
//合并两个链表
t1=head.next;
t2=fs;
tt=head;
while(t1!=null || t2!=null){
if(t2!=null){
tt.next=t2;
t2=t2.next;
tt=tt.next;
}
if(t1!=null){
tt.next=t1;
t1=t1.next;
tt=tt.next;
}
}
return;
}
}