题目:
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
给定一个链表L:L0→L1→…→Ln-1→Ln
排序使之成为: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}
.
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
//解题思路:找到中间结点,断开,把后半段链表翻转一下,然后再合并两个链表
//翻转链表
ListNode* reverse(ListNode *head)
{
if (head == nullptr || head->next == nullptr)
return head;
//定义三个结点,分别保存前一个,当前,和后一个结点
ListNode *prev = head;
ListNode *curr = head->next;
ListNode *next = curr->next;
while(curr)
{
curr->next = prev; //使当前结点指向前一个结点
prev = curr;//向后移动
curr = next;
if(curr == NULL)//如果当前结点为空,说明遍历结束
break;
if(next->next == NULL)//如果next为最后一个结点,则next没有next了,那么令next为空
next = NULL;
else
next = next->next;
}
head->next = nullptr;//头结点变成了最后一个结点,所以head->next置为空
return prev;//返回新链表的头结点
}
void reorderList(ListNode *head)
{
if(head == NULL || head->next == NULL)
return;
ListNode *slow = head;
ListNode *fast = head;
ListNode *prev = NULL;
//循环结束时,如果链表个数为偶数,则slow到达中间偏后一个结点(n/2+1),fast为NULL;
//如果链表个数为奇数,则slow到达中间, fast到达最后一个节点(非空)
while(fast && fast->next)
{
prev = slow;
slow = slow->next;//slow加1
fast = fast->next->next;//fast连续加两个
}
prev->next = NULL;//链表分成两段,前一段到(n/2)
slow = reverse(slow);//把后一段链表翻转一下,返回新链表的头结点
ListNode *curr = head;
while(curr->next)
{
ListNode *tmp = curr->next;//暂时保存curr的下一个结点
curr->next = slow;
slow = slow->next;
curr->next->next = tmp;
curr = tmp;
}
curr->next = slow;//后一个链表的长度>=前一个链表
}
};