给定一个单链表L: L0→L1→…→Ln-1→Ln,
重新排列后为:L0→Ln→L1→Ln-1→L2→Ln-2→…
必须在不改变节点值的情况下进行原地操作。
样例
给出链表 1->2->3->4->null
,重新排列后为1->4->2->3->null
。
挑战
Can you do this in-place without altering the nodes' values?
解题思路:
先使用快慢指针,找到中间元素,然后将其对半分为前后两个链表。然后将后半部分链表翻转,最后链接前后链表即可。
注意快慢指针找中间元素,最后只与slow指针有关。fast后被重新定义为后链表头。
翻转后链表的操作步骤与Lintcode 35:Reverse Linked List相同。
/**
* Definition of singly-linked-list:
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The head of linked list.
* @return: nothing
*/
void reorderList(ListNode * head)
{
// write your code here
if(head == NULL || head->next == NULL)
return;
ListNode * slow = head;
ListNode * fast = head;
//利用快慢指针寻找中间位置
while(fast->next != NULL && fast->next->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
//运行完毕后,[head,slow]为前半部分链表,(slow,NULL]为后半部分链表
fast = slow->next;//重定义fast指向后半部分链表的头部
slow->next = NULL;//将前部部分链表尾部加上NULL
fast->next = NULL;//将后半部分链表尾部加上NULL
//*****************翻转链表操作*********************
ListNode * pre = fast;
ListNode * cur = pre->next;
//翻转后半部分链表
while(cur != NULL)
{
ListNode * next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
//*************************************************
//后半部分链表翻转后,pre指向了后链表的头部
cur = head;//重定义cur为遍历前部分链表的指针
//连接前后两部分链表
while(cur != NULL && pre != NULL)
{
ListNode * preAfter = pre->next;
pre->next = cur->next;
cur->next = pre;
cur = cur->next->next;
pre = preAfter;
}
}
};
扫描二维码关注公众号,回复:
2259548 查看本文章