题目:
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}.
思路:将链表分成两半,然后将后面一半的链表反转,再和前面一半的链表结合起来就可以了。
关键问题:
1. 将链表分成两半,需要确定中间结点的位置,由于是单链表,我们不能让一个指针从后往前走,一个指针从前往后走。这里我们可以使用快慢指针,即从head开始,快指针每次走两步,而慢指针每次走一步,这样,当快指针走到末尾时,慢指针刚好走到中间结点。
2. 链表的反转,我们使用三个指针遍历链表,进行结点逐个反转。
时间复杂度O(n),空间复杂度O(1)
代码:
#include "stdafx.h"
#include <iostream>
using namespace std;
struct ListNode
{
int val;
ListNode* next;
ListNode(int x): val(x), next(nullptr){}
};
class Solution
{
public:
void reorderList(ListNode* head);
private:
ListNode* reverseList(ListNode* head);
};
void Solution::reorderList(ListNode* head)
{
if (nullptr == head || nullptr == head->next)
return;
//使用快慢指针找到中间结点
ListNode* fast = head;
ListNode* slow = head;
while (nullptr != fast->next && nullptr != fast->next->next)
{
fast = fast->next->next;
slow = slow->next;
}
ListNode* mid = slow->next;
ListNode* head2 = reverseList(mid);
slow->next = nullptr;
ListNode* temp = head->next;
while (nullptr != head && nullptr != head2)
{
temp = head->next;
head->next = head2;
head2 = head2->next;
head->next->next = temp;
head = temp;
}
}
// 逆转链表,逐个链接点进行反转
ListNode* Solution::reverseList(ListNode* head)
{
if (nullptr == head || nullptr == head->next)
return nullptr;
ListNode* p1 = head;
ListNode* p2 = head->next;
while (nullptr != p2)
{
ListNode* temp = p2->next; //要改变p2->next的指针,必须先保留p2->next
p2->next = p1;
p1 = p2; //循环往后
p2 = temp;
}
head->next = nullptr; //原先的head已经变成了tail,别忘了置空,只有到这步才能置空
return p1;
}
int main()
{
ListNode* pNode1 = new ListNode(1);
ListNode* pNode2 = new ListNode(2);
ListNode* pNode3 = new ListNode(3);
ListNode* pNode4 = new ListNode(4);
ListNode* pNode5 = new ListNode(5);
pNode1->next = pNode2;
pNode2->next = pNode3;
pNode3->next = pNode4;
pNode4->next = pNode5;
pNode5->next = nullptr;
Solution objSolution;
objSolution.reorderList(pNode1);
while (pNode1 != nullptr)
{
cout<<pNode1->val<<endl;
pNode1 = pNode1->next;
}
delete pNode1;
delete pNode2;
delete pNode3;
delete pNode4;
system("PAUSE");
return 0;
}