题目描述
给定一个单链表 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.
思路分析
- 方法一:线性表
- 方法二:寻找链表中点 + 链表逆序 + 合并链表
代码实现
/**
* 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:
//找到中间结点,选择快慢指针(当结点总数是偶数时,中间结点有两个;如果循环条件为fast!=NULL && fast->next != NULL,此时slow返回的第二个中间结点;如果循环条件为fast->next != NULL && fast->next->next != NULL,此时slow返回第一个中间结点)//
ListNode* findMid(ListNode* head){
ListNode *slow = head, *fast = head;
while(fast->next != NULL && fast->next->next != NULL){
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
//反转链表
ListNode* reverseList(ListNode* head){
ListNode *pre = NULL, *cur = head;
ListNode *nextNode;
while(cur != NULL){
nextNode = cur->next;
cur->next = pre;
pre = cur;
cur = nextNode;
}
return pre;
}
//合并两个链表
ListNode* mergeList(ListNode* head1, ListNode* head2){
ListNode *next1 = head1, *next2 = head2;
while(head1 != NULL && head2 != NULL){
next1 = head1->next;
head1->next = head2;
head1 = next1;
next2 = head2->next;
head2->next = head1;
head2 = next2;
}
return head1;
}
void reorderList(ListNode* head) {
//找到中间结点(中间结点有两个时,找到第一个);给第一个链表的尾部添加空指针,保持完整性
ListNode *middleNode = findMid(head);
ListNode *head2 = middleNode->next;
middleNode->next = NULL;
//反转第二个链表,合并两个链表
head2 = reverseList(head2);
ListNode *head1 = head;
mergeList(head1, head2);
}
};
复杂度
- 时间复杂度O(N)
- 空间复杂度O(1)