原题链接:https://leetcode-cn.com/problems/reorder-list/
1、map
void reorderList(ListNode* head) {
map<int,ListNode*> map;
ListNode *p=head;
int n=0;
while(p!=NULL){//使用map将链表顺序存储
map[n]=p;
p=p->next;
n++;
}
for(int i=0,j=n-1;i<j;i++,j--){//每次取i+j==1+n的节点链接即可
int pre=j-1;
map[pre]->next=map[j]->next;
map[j]->next=map[i]->next;
map[i]->next=map[j];
}
}
2、递归★★
void reorderList(ListNode* head) {
if(head==NULL||head->next==NULL||head->next->next==NULL){
return;
}
int len=0;
ListNode *p=head;
while(p!=NULL){//求出节点数
len++;
p=p->next;
}
reorderListHelper(head,len);
}
ListNode *reorderListHelper(ListNode *head,int len){
if(len==1){
ListNode *outTail=head->next;
head->next=NULL;
return outTail;
}
if(len==2){
ListNode *outTail=head->next->next;
head->next->next=NULL;
return outTail;
}
ListNode *tail=reorderListHelper(head->next,len-2);//相当于快慢指针,当len==1时,总数为奇数,head正好走到中点;当len==2时,总数为偶数,head走到中间左边的节点。
ListNode *subHead=head->next;//子链表的头结点
head->next=tail;
ListNode *outTail=tail->next;//上一层head对应的tail
tail->next=subHead;
return outTail;
}
3、双链表
示例:
1 -> 2 -> 3 -> 4 -> 5 -> 6
第一步,将链表平均分成两半
1 -> 2 -> 3
4 -> 5 -> 6
第二步,将第二个链表逆序
1 -> 2 -> 3
6 -> 5 -> 4
第三步,依次连接两个链表
1 -> 6 -> 2 -> 5 -> 3 -> 4
代码:
void reorderList(ListNode* head) {
if(head==NULL||head->next==NULL) return;
ListNode *p=head,*q=head;
while(q->next!=NULL&&q->next->next!=NULL){//找到中点,如果总长度是偶数,p,q长度相同;如果总长度是奇数,p比q长一个
p=p->next;
q=q->next->next;
}
q=reverse(p->next);//分隔链表,并且将后半部分倒序
p->next=NULL;
p=head;
while(q!=NULL){//再将两个链表交错合并
ListNode *tmp=q->next;
q->next=p->next;
p->next=q;
p=q->next;
q=tmp;
}
}
ListNode* reverse(ListNode* head){//递归倒序
if(head->next==NULL) return head;
ListNode* last=reverse(head->next);
head->next->next=head;
head->next=NULL;
return last;
}