思路:把链表后半部分翻转,然后穿插构成新链表,这里注意一下如果是奇数,快慢指针返回slow,偶数返回slow->next。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* halfhead(struct ListNode* head)
{
struct ListNode* fast=head;
struct ListNode* slow=head;
while(fast->next && fast->next->next)
{
fast=fast->next->next;
slow=slow->next;
}
if(fast->next==NULL)
return slow;
else return slow->next;
}
struct ListNode* reverList(struct ListNode* head)
{
struct ListNode* newhead=NULL;
struct ListNode* ptake=head;
struct ListNode* pbroke=head->next;
while(1)
{
ptake->next=newhead;
if(pbroke==NULL) return ptake;
newhead=ptake;
ptake=pbroke;
pbroke=pbroke->next;
}
}
void reorderList(struct ListNode* head){
struct ListNode* halfh=halfhead(head);
struct ListNode* head2=reverList(halfh);
int l=0;
struct ListNode* head3=head;
struct ListNode* tail=head;
head=head->next;
while(head2!=NULL && head!=NULL)
{
if(l==0)
{tail->next=head2;
tail=tail->next;
head2=head2->next;
l=1;}
else
{
tail->next=head;
tail=tail->next;
head=head->next;
l=0;
}
}
while(head3)
{
printf("%d ",head3->val);
head3=head3->next;
}
}
思路:链表分为两种情况,相交和不相交,我们用双指针来做,例如:
链表A不相交长度是a,链表B不相交长度是b,相交长度是c。所以分两种情况来看,
(1)如果a=b,而且不得null,两指针同时指向链表交点。
(2)如果a!=b,那么当指针pa走过路程a+b+c时,指针pb走过b+c+a时,两指针相遇,指向链表交点,这个过程就是pa走到表尾时指向B链表表头,然后等到pb走到表尾时指向A链表表头。
这两种情况是相交的时候,判断是否到焦点的条件是,pa=pb且pa!=NULL。
在不相交的时候:
(1)如果两链表长度相等,那么会同时指向NULL。
(2)如果两链表长度不相等时,pa走到表尾时指向B链表表头,然后等到pb走到表尾时指向A链表表头,她两走了相同的路程后都指向了NULL。
所以这两种情况的判断条件是:pa==pb 且pa==NULL
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(headA==NULL || headB==NULL)return NULL;
struct ListNode *pa=headA;
struct ListNode *pb=headB;
while(pa!=pb)
{
if(pa==pb && pa!=NULL)return pa;
if(pa==pb && pa==NULL)return pa;
if(pa==NULL) pa=headB;
else pa=pa->next;
if(pb==NULL) pb=headA;
else pb=pb->next;
}
return pa;
}
LCR 022. 环形链表 II - 力扣(LeetCode)
如图所示
我们用快慢指针算法,链表中环外部分的长度为a,快慢指针在紫色点相遇,相遇时慢指针走了b长度,相遇时快指针已经走完了环的 n 圈,快指针走过的长度为 a+n(b+c)+b。慢指针走过的长度为a+b,由于快指针走过的距离为慢指针的二倍,所以2*(a+b)=a+n(b+c)+b。
由于我们要找到入环点,所以等式左面为a,推出a=c+(n-1)*(b+c),也就是说再设置一个指针p,当它走到入环点的时候慢指针从紫色节点走了(n-1)圈+c,慢指针和p同时到了入环点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow=head;
struct ListNode* fast=head;
struct ListNode* p=head;
while(fast!=NULL)
{
if(fast->next==NULL || fast->next->next==NULL)return NULL;
slow=slow->next;
fast=fast->next->next;
if(slow==fast)break;
}
while(p!=slow)
{
p=p->next;
slow=slow->next;
}
return p;
}
先复制next指针指向,再复制random指针指向,再拆分。
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head) {
if(head==NULL)return NULL;
for(struct Node* nodehead=head;nodehead!=NULL;nodehead=nodehead->next->next)
{
struct Node* newnode=(struct Node*)malloc(sizeof(struct Node));
newnode->val=nodehead->val;
newnode->next=nodehead->next;
nodehead->next=newnode;
}
for(struct Node* nodehead=head;nodehead!=NULL;nodehead=nodehead->next->next)
{
nodehead->next->random=nodehead->random==NULL?NULL:nodehead->random->next;
}
struct Node* new=head->next;
for(struct Node* nodehead=head;nodehead!=NULL;nodehead=nodehead->next)
{
struct Node* newhead=nodehead->next;
nodehead->next=nodehead->next->next;
newhead->next=(nodehead->next==NULL)?NULL:nodehead->next->next;
}
return new;
}