问题描述
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You may not modify the values in the list’s nodes, only nodes itself may be changed.
Example 1:
Given 1->2->3->4, reorder it to 1->4->2->3.
Example 2:
Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
思路分析
给一个链表,将它重新调整为高斯公式相加这样相连的样子。
分为三步,第一步,将链表分为两半,使用快慢指针完成。
第二步,将后半部分的链表翻转,slow指针可以作为dummy head来帮助完成翻转。用一个temp节点指向cur->next,不断的将cur后的结点拿到dummy head之后插入进去,完成翻转。
第三步,在head没到达premiddle的时候,将对应位置的节点连起来。要注意先连p2到p1->next,再连p1->p2,然后移动两个指针。很重要的一点,用premiddle->next保存p2->next。
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
if (!head || !head->next)
return;
ListNode* slow = head;
ListNode* fast = head;
//find the middle
while(fast->next && fast->next->next){
slow = slow->next;
fast = fast->next->next;
}
//reverse the second half of list
ListNode* premiddle = slow;
ListNode* cur = slow->next;
while (cur->next){
ListNode* temp = cur->next;
cur->next = temp->next;
temp->next = premiddle->next;
premiddle->next = temp;
}
//link them one by one
ListNode* p1 = head;
ListNode* p2 = premiddle->next;
while (p1 != premiddle){
premiddle->next = p2->next;
p2->next = p1->next;
p1->next = p2;
p1 = p2->next;
p2 = premiddle->next;
}
}
};
时间复杂度:
O(n)
空间复杂度:
O(1
反思
困扰了我很长的时间,主要是对于翻转链表操作的不理解。链表的题目不能靠想象,需要画图表示处算法处理的方式。