给定一个单链表L: L0→L1→…→Ln-1→Ln,
重新排列后为:L0→Ln→L1→Ln-1→L2→Ln-2→…
必须在不改变节点值的情况下进行原地操作
样例
给出链表 1->2->3->4->null
,重新排列后为1->4->2->3->null
。
思路:1、将链表等分
2、将第二个链表翻转
3、 交叉合并链表
这个题开始思路是这样的,写代码时犯了很多错误,一直改改改,最后借鉴了别人的代码,发现了很多自己的错误,结合自己的代码,如下
1、 例1->3->4->5->6->7->null
class Solution {
public:
/*
* @param head: The head of linked list.
* @return: nothing
*/
void reorderList(ListNode * head) {
//注意此处返回值为void,故做题时,最后的链表值应以head为第一个结点,即head不能动
// write your code here
if(head == NULL || head->next == NULL || head->next->next==NULL)
return;
//找到中间节点,并将它们等分,利用快慢指针
ListNode *slow=head,*fast=head->next;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}//slow为链表中间点 1->3->4->null 5->6->7->null
ListNode *second=slow->next;
slow->next=NULL;
//翻转第二个链表 7->6->5->null
ListNode *sec=reverlist(second);
//合并链表 1->7->3->6->4->5->null
ListNode *p=head->next,*s=head,*q=sec;
while(p&&q)
{
s->next=q;
s=s->next;//此处是s=s->next,不是s=q,容易出错
q=q->next;
s->next=p;
s=s->next;//同上
p=p->next;
}
if(p)
s->next=p;
if(q)
s->next=q;
}
//翻转链表函数
ListNode* reverlist(ListNode *head)
{
ListNode *pre=NULL;
ListNode *cur=head;
ListNode *next;
while(cur!=NULL)
{
next=cur->next;
cur->next=pre;
pre=cur;
cur=next;
}
return pre;
}
};
二、还可将链表转移到vector中做
class Solution {
public:
/*
* @param head: The head of linked list.
* @return: nothing
*/
void reorderList(ListNode * head) {
// write your code here
if (head == NULL)
return;
vector<ListNode*> nodes;
ListNode* iter = head;
while(iter != NULL)
{
nodes.push_back(iter);
iter = iter->next;
}
int LEN = nodes.size();
int left = 0;
int right = LEN -1;
while(left < right)
{
nodes[left]->next = nodes[right];
nodes[right--]->next = nodes[++left];
}
nodes[left]->next = NULL;
}
};