/**
给定一个单链表?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.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reorder-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
- Definition for singly-linked list.
- struct ListNode {
-
int val;
-
ListNode *next;
-
ListNode(int x) : val(x), next(NULL) {}
- };
*/
/*
分三步走
1.寻找中间结点
2.逆置后半结点
3.重新插入
/
class Solution {
public:
void reorderList(ListNode head) {
ListNode *fast,*slow;
if(head==NULL)
return;
slow=head;
fast=head->next;//依旧使用快慢指针得到中间节点
while(fast!=NULL&&fast->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;
}
ListNode *right=reverse(slow->next);
slow->next=NULL;
ListNode *left=head;
while(right)//拼接
{
ListNode *temp=right->next;
if(left==NULL||right==NULL)
return;
right->next=left->next;
left->next=right;
right=temp;
left=left->next->next;
}
}
ListNode *reverse(ListNode *head)//转置后半段元素
/*
转置分四步
1.先提出后一个节点temp(指向)
2.head指向prev(即前一个节点,无就是NULL)
3. prev取代head
4.head取代(指向)temp
*/
{
ListNode *prev=NULL;
if(head==NULL)
return NULL;
while(head!=NULL)
{
ListNode *temp=head->next;//1.先提出后一个节点temp(指向)
head->next=prev;//2.head指向prev(即前一个节点,无就是NULL)
prev=head;//3. prev取代head
head=temp;//4.head取代(指向)temp
}
return prev;
}
};
此题用的是
折中逆置法
逆置是很关键的一种方法,不需要开辟额外的空间,在原链表上做变动即可,而且也不费太多时间
蓝文昊大佬提供的其他思路:
1.遍历链表,并且遍历的同时让后一个节点指向前一个节点,以此建立双向链表
2.填表法:建立一个指针数组,然后一一对应,改变位置即可!
3.找到链表尾部,依次插入。但是这种做法太费时间,无法pass
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
int i,len;
len=lenList(head);
ListNode *tail,*pretail,*pre=head;
if(pre==NULL)
return;
for(i=0;i<len/2;i++)
{
tail=tailList(head);
pretail=preTailList(head);
if(tail==NULL||pre==NULL)
return;
tail->next=pre->next;
pre->next=tail;
pretail->next=NULL;
pre=pre->next->next;
}
}
int lenList(ListNode *head)
{
int len=0;
ListNode *p=head;
if(p==NULL)
return NULL;
while(p)
{
len++;
p=p->next;
}
return len;
}
ListNode *tailList(ListNode *head)
{
ListNode *p=head;
if(p==NULL)
return NULL;
while(p->next)
{
p=p->next;
}
return p;
}
ListNode *preTailList(ListNode *head)
{
ListNode *p=head;
if(p==NULL)
return NULL;
while(p->next&&p->next->next)
{
p=p->next;
}
return p;
}
};
最后这道题发现的一个很大的
坑
!!!!!!!!!
学校教的链表头节点是不赋值的,但是这里是赋值的!!!!这会导致多出入一个next!