【leetcode】143. Reorder List
题目说明
https://leetcode-cn.com/problems/reorder-list/description/
给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
解法1
首先利用快慢指针找到链表中间结点mid,然后从head遍历到mid,遍历时,将对应的尾部结点插入到当前结点之后。
找尾部对应结点时,从mid遍历到尾部找到对应的尾部结点。整个过程进行了双重循环,时间复杂度较高。还是推荐解法2。
时间复杂度:O(n^2)
/*
* 时间复杂度:O(n^2)
* 先找到中间结点mid
* 从head遍历到mid,遍历时,将对应的尾部结点插入到当前结点之后
*/
void reorderList(ListNode* head) {
if (head == NULL || head->next == NULL)
return;
ListNode *slow = head;
ListNode *fast = head;
while(fast->next && fast->next->next){
slow = slow->next;
fast = fast->next->next;
}
ListNode *mid = slow;
ListNode *pre = head;
ListNode *lastpre = NULL;
ListNode *tmp = NULL;
ListNode *moveNode = NULL;
while(pre != mid){
lastpre = mid;
while(lastpre->next && lastpre->next->next)//找到尾部结点前一个结点
lastpre = lastpre->next;
moveNode = lastpre->next;
tmp = pre->next;
pre->next = moveNode;
moveNode->next = tmp;
lastpre->next = NULL;
pre = tmp;
}
return ;
}
解法2
首先利用快慢指针找到链表中间结点mid,然后将之后的链表进行反转。
然后同时遍历正向与反向链表,将反向链表对应结点插入到正向链表结点之后。
这样遍历了三次链表,时间复杂度:O(n)。
/*
* 时间复杂度:O(n)
* 找到中结点后,将之后的链表进行反转
* 然后从两个链表头结点(即原链表的头尾)开始遍历
* 将反向链表的相应结点插入到正向链表之后
*/
void reorderList(ListNode* head) {
if (head == NULL || head->next == NULL)
return;
ListNode *slow = head;
ListNode *fast = head;
//找到中间结点
while(fast->next && fast->next->next){
slow = slow->next;
fast = fast->next->next;
}
ListNode *mid = slow;
ListNode *pre = NULL;
ListNode *last = mid->next;
ListNode *tmp = NULL;
ListNode *tmp1 = NULL;
//中结点之后置为空,正向链表尾部指向NULL
mid->next = NULL;
//反转中结点之后的链表,反向链表尾部指向初始的pre即NULL
while(last){
tmp = last->next;
last->next = pre;
pre = last;
last = tmp;
}
ListNode *headNode = head;
ListNode *tailNode = pre;
//同时遍历正向与反向链表,将反向链表对应结点插入到正向链表结点之后
while(headNode && tailNode){
tmp = headNode->next;
tmp1 = tailNode->next;
headNode->next = tailNode;
tailNode->next = tmp;
headNode = tmp;
tailNode = tmp1;
}
return ;
}