题目描述
将给定的单链表L: L0→L1→…→Ln-1→Ln
重新排序为:L0→Ln →L1→Ln-1→L2→Ln-2→…
要求使用原地算法,不能改变节点内部的值,需要对实际的节点进行交换。
例如:对于给定的单链表{1,2,3,4},将其重新排序为{1,4,2,3}.
思路
这道题要将给定的单链表进行重新排序,排序的规则为L0→Ln →L1→Ln-1→L2→Ln-2→…,也就是放一个开头的再放一个末尾的,直到下标相遇时停止。
因为题目要求使用原地算法,因此不应该申请额外的O(n)辅助空间(如果申请了额外空间就很简单了)。
要解决这个问题,我们需要找到中间结点,然后将中间结点后面的剩余链表进行反转得到一个新链表L1,然后再和中间结点前面的顺序链表L0进行合并,合并时先放一个L0结点再放一个L1结点,直到L0、L1都到达末尾。
具体找中间结点的方法是使用快慢指针,一快一满,两个指针都从头结点开始往后移动,快指针一次动两个单位(即移到->next->next),慢指针一次动一个单位(移到->next),当快指针到达末尾时终止查找,此时慢指针所处的位置就是中间结点。
因为链表长度有奇偶两种情况,因此判断快指针到达末尾时需要注意判断两个条件:fast->next!=NULL&&fast->next->next!=NULL
ListNode *slow=head,*fast=head,*reverse_head=NULL,*p,*before=NULL,*after;
//快慢指针找出中间结点
while(fast->next!=NULL&&fast->next->next!=NULL){
//链表大小可为奇偶,因此要满足两个条件
fast=fas