22. 两两交换链表中的节点
struct ListNode* swapPairs(struct ListNode* head){
typedef struct ListNode ListNode;
ListNode*dummyHead=(ListNode*)malloc(sizeof(ListNode));
dummyHead->next=head;
ListNode*cur=dummyHead;
while(cur->next!=NULL&&cur->next->next!=NULL){
ListNode*tmp1=cur->next;//交换后头结点已变化,不能用head->next
ListNode*tmp2=cur->next->next->next;
cur->next=cur->next->next;
cur->next->next=tmp1;
cur->next->next->next=tmp2;
cur=cur->next->next;
}
return dummyHead->next;
}
- 修改某个节点的指针,一定要知道前一个节点的指向
- 本题采用模拟法,链表题目一定要画图
- 防止断链,记录临时指针
19. 删除链表的倒数第 N 个结点
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
typedef struct ListNode ListNode;
ListNode*dummyHead=(ListNode*)malloc(sizeof(ListNode));
dummyHead->val=0;
dummyHead->next=head;
ListNode*fast=head;
ListNode*slow=dummyHead;
for(int i=0;i<n;i++){
fast=fast->next;
}
while(fast){
fast=fast->next;
slow=slow->next;
}
slow->next=slow->next->next;
head=dummyHead->next;//需要更新头结点,因为可能删除的是头结点
free(dummyHead);
return head;
}
- 删除某个节点,找到前一个节点
- 虚拟头结点:统一操作进行删除
- 双指针法:快指针先移动n+1步,然后快慢指针同时移动,快指针指向空,慢指针指向要删除的节点的前一个
- 模拟赋值法
面试题 02.07. 链表相交
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
typedef struct ListNode ListNode;
ListNode*l=headA;//假设headA长
ListNode*s=headB;
//计数
int lenA,lenB,gap=0;
while(l){
lenA++;
l=l->next;
}
while(s){
lenB++;
s=s->next;
}
//差值
if(lenA>lenB){
l=headA,s=headB;
gap=lenA-lenB;
}else{
l=headB,s=headA;
gap=lenB-lenA;
}
//齐步
while(gap--)l=l->next;
while(l)//两者已齐步,判断一个即可
{
if(l==s){
return l;
}
l=l->next;
s=s->next;
}
return NULL;
}
142. 环形链表 II
struct ListNode *detectCycle(struct ListNode *head) {
typedef struct ListNode ListNode;
ListNode*fast=head,*slow=head;
while(fast&&fast->next)//链表无环则跳出
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow){
ListNode*mfast=fast,*mhead=head;
while(mfast!=mhead){
mfast=mfast->next;
mhead=mhead->next;
}
return mfast;
}
}
return NULL;
}
- 快指针在环里一个节点一个节点的靠近慢指针,快指针从头出发,慢指针从相遇处出发,遇到的地方就是入口
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9a76f0833ca972d0fe7b790c28e63159.png)