Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to:
L0→Ln→L1→Ln-1→L2→Ln-2→…You must do this in-place without altering the nodes’ values.
For example, Given {1,2,3,4}, reorder it to {1,4,2,3}.
又是一个链表改序的问题,古老的办法当然是每次找最末尾,然后将最末尾插入到前面想要的位置。
然后发现一个很大很大的用例TLE了
//可以看到,暴力的办法超时了
for(ListNode* cur=head;i<n/2;i++){
//获取到最后一个节点
temp=cur;
ListNode* t=temp->next;
int count=1;
//不能少于3个元素才能进行交换
for(;t->next!=NULL;t=t->next,temp=temp->next) count++;
//得到t为最后一个节点
if(count<2) break;
t->next=cur->next;
cur->next=t;
cur=cur->next->next;
//找到temp前一个设置为队尾
temp->next=NULL;
//break
if(cur==NULL) break;
}
正确的办法应当是算出后面有多少元素需要倒置,然后倒置它们,将这些链表提取出来依次插入另一个链表
处理一些莫名的re之后就可ac
class Solution {
public:
void reorderList(ListNode* head) {
if(head==NULL) return;
ListNode root(-1),new_head(-1);
root.next=head;
int n=1,i=0;//计算链表的长度
ListNode* temp=head;
for(;temp->next!=NULL;n++,temp=temp->next);
if(n<=2) return;//2个节点以内不需要进行处理
int k=(n-1)/2;
//可以确定这个end是目的链表的end
ListNode *end=head;
for(int i=0;i<n/2;i++,end=end->next);
//划分为两个链表
new_head.next=end->next;
end->next=NULL;
//反转第二链表
reverse(&new_head,new_head.next,temp);
//将第二链表插入第一链表
for(ListNode *st=head,*sub=new_head.next,*stmp=NULL;sub;){
stmp=sub->next;
sub->next=st->next;
st->next=sub;
st=sub->next;
sub=stmp;
}
}
ListNode* reverse(ListNode* preNode,ListNode* begin,ListNode* end){
//首尾是一个节点。不需要处理
if(begin==end) return begin;
ListNode* end_next=end->next;
for(ListNode *p=begin,*cur=p->next,*next=cur->next;
cur != end_next;
p=cur,cur=next,next=next?next->next:NULL){
cur->next=p;
}
begin->next=end_next;
preNode->next=end;
return begin;
}
};