题目描述
Given a singly linked list L : L0 ! L1 ! · · · ! Ln−1 ! Ln, 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}.
首先,题目规定要in-place,也就是说只能使用O(1)的空间
解题思路
- 观察新链表,它是在原链表的基础上一头一尾交替连接而成,所以原链表的前半段在新链表中是顺序的,后半段在新链表中是逆序的
- 所以,我们的解题思路就是:通过快慢指针找到链表的中间节点,然后从中间节点处断开,将后半段链表进行逆置,然后将后半段链表节点插入到前半段链表中
- 理清思路后,我们就可以开始写代码了,这个题的实现不但考察了我们接着道题的思路,同时也考察了链表逆置的算法
代码实现
- void reorderList(ListNode *head)
void reorderList(ListNode *head)
{
//如果链表为空,有一个节点,有两个节点,则不用进行处理
if(head == NULL || head->next == NULL || head->next->next == NULL)
return;
//通过快慢指针寻找中间节点
ListNode* fast = head;
ListNode* slow = head;
ListNode* prev = NULL;
while(fast != NULL && fast->next != NULL)
{
prev = slow;
slow = slow->next;
fast = fast->next->next;
}
//将链表从slow(中间节点)处断开
prev->next = NULL;
//将链表的后半段进行逆置
slow = reverse(slow);
//将两条链表进行插入合并
head = merge(head, slow);
}
- 下面我们考虑链表逆置的实现,我们通过一张图来看一下链表逆置的过程,以帮助我们思路更清晰的写出代码,如下图所示:
- 代码实现如下:
ListNode* reverse(ListNode* head)
{
if(head == NULL || head->next == NULL)
return head;
ListNode* cur = head;
ListNode* prev = head;
ListNode* next = cur->next;
cur->next = NULL
while(next != NULL)
{
prev = cur;
cur = next;
next = cur->next;
cur->next = prev;
}
//最后一个节点单独处理
cur->next = prev;
prev = cur;
return prev;
}
- 最后是两条链表进行插入合并的实现:
//我们此处进行的是后半段链表在前半段链表的基础上插入合并
ListNode* merge(ListNode* head1, ListNode* head2)
{
//两条链表都非空
ListNode* cur = head1;
ListNode* next = NULL;
while(cur->next != NULL)
{
next = cur->next;
cur->next = head2;
head2 = head2->next;
cur->next->next = next;
cur = next;
}
cur->next = head2;
return head1;
}
- 代码的完整实现如下:
ListNode* reverse(ListNode* head)
{
if (head == NULL || head->next == NULL)
return head;
ListNode* cur = head;
ListNode* prev = head;
ListNode* next = cur->next;
cur->next = NULL;
while (next != NULL)
{
prev = cur;
cur = next;
next = cur->next;
cur->next = prev;
}
//最后一个节点单独处理
cur->next = prev;
prev = cur;
return prev;
}
ListNode* merge(ListNode* head1, ListNode* head2)
{
//两条链表都非空
ListNode* cur = head1;
ListNode* next = NULL;
while (cur->next != NULL)
{
next = cur->next;
cur->next = head2;
head2 = head2->next;
cur->next->next = next;
cur = next;
}
cur->next = head2;
return head1;
}
void reorderList(ListNode *head)
{
//如果链表为空,有一个节点,有两个节点,则不用进行处理
if (head == NULL || head->next == NULL || head->next->next == NULL)
return;
//通过快慢指针寻找中间节点
ListNode* fast = head;
ListNode* slow = head;
ListNode* prev = NULL;
while (fast != NULL && fast->next != NULL)
{
prev = slow;
slow = slow->next;
fast = fast->next->next;
}
//将链表从slow(中间节点)处断开
prev->next = NULL;
//将链表的后半段进行逆置
slow = reverse(slow);
//将两条链表进行插入合并
head = merge(head, slow);
}
int main()
{
ListNode* node1 = new ListNode(1);
ListNode* node2 = new ListNode(2);
ListNode* node3 = new ListNode(3);
ListNode* node6 = new ListNode(6);
ListNode* node7 = new ListNode(7);
node1->next = node2;
node2->next = node3;
node3->next = node6;
node6->next = node7;
PrintList(node1);
reorderList(node1);
PrintList(node1);
return 0;
}
- 程序运行结果如下图所示: