给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2:
给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.
来源:力扣(LeetCode)
方法一
本题最直接的方法把 list 转成 vector,然后通过下标交替取前一个后一个进行重排即可。
方法二
由上图可知,重排的结果是:
①:原 list 分成左右两部分
②:对右半部分进行逆序操作
③:两部分交替从前往后取节点进行重组
涉及到的知识点有使用快慢指针得到链表中间节点、链表的逆序操作、链表的遍历与合并。
代码示例
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
ListNode * leftList = head;
ListNode * rightList = getMidNode(head);
ListNode * leftlast = rightList;
rightList = reverseList(rightList);
ListNode * left = leftList;
ListNode * right = rightList;
ListNode * temp = new ListNode(0);
while( left != leftlast || right != nullptr )
{
if( left != leftlast )
{
temp->next = left;
temp = temp->next;
left = left->next;
}
if( right != nullptr )
{
temp->next = right;
temp = temp->next;
right = right->next;
}
}
head = temp->next;
}
ListNode* getMidNode(ListNode* head)
{
ListNode * fast = head;
ListNode * slow = head;
while(fast && fast->next)
{
fast = fast->next;
fast = fast->next;
slow = slow->next;
}
return slow;
}
ListNode * reverseList(ListNode* head)
{
ListNode * prenode = nullptr;//前个节点
ListNode * node = head;//当前节点
ListNode * nextnode = head;//下个节点
while( node )
{
nextnode = node->next;//保存下个节点
node->next = prenode; //当前节点连到上个节点
prenode = node;//更新上个节点
node = nextnode ;//更新当前节点
}
return prenode;
}
};