24. 两两交换链表中的节点
题目链接/文章讲解/视频讲解: 代码随想录
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode*dummyhead=new ListNode(0);//创建虚拟头结点
dummyhead->next=head;
ListNode*cur=dummyhead;
ListNode*temp=new ListNode(0);
ListNode*temp1=new ListNode(0);
while(cur->next!=NULL&&cur->next->next!=NULL)//注意不能交换顺序,先偶后奇,先判断cur->next!=null才能继续走下去
{
temp=cur->next;//先保存第一个节点
temp1=cur->next->next->next;//保存第三关节点
cur->next=cur->next->next;//节点1的前线已经断掉,所以需要先保存一下第一个节点
cur->next->next=temp;//节点2的前线已经断,所以先需要保存节点3,保证不断掉
temp->next=temp1;
cur=cur->next->next;//cur往后移两位
}
return dummyhead->next;
delete dummyhead;
}
};
两个临时节点 (tmp
和 tmp1
) 的作用是:
tmp
保存第一个节点,以防丢失;tmp1
保存后续节点,确保交换后的链表部分能够正确连接。
while(cur->next!=NULL&&cur->next->next!=NULL)
注意不能交换顺序,先偶后奇,先判断cur->next!=null才能继续走下去,否则出现空指针异常
19.删除链表的倒数第N个节点 (快慢指针)
题目链接/文章讲解/视频讲解:代码随想录
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode*dummyhead=new ListNode(0);
dummyhead->next=head;
ListNode*fast=dummyhead;
ListNode*slow=dummyhead;
int m=n+1;
while(m--)
{
fast=fast->next;
}
while(fast!=NULL)
{
fast=fast->next;
slow=slow->next;
}
ListNode*temp=slow->next;
slow->next=slow->next->next;
delete temp;
return dummyhead->next;
}
};
面试题 02.07. 链表相交
题目链接/文章讲解:代码随想录
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode*cur1=headA;
ListNode*cur2=headB;
int size1=0;
int size2=0;
//交点不是数值相等,而是指针相等,所以链表应该右对齐
while(cur1!=NULL)
{
cur1=cur1->next;
size1++;
}
while(cur2!=NULL)
{
cur2=cur2->next;
size2++;
}
cur1=headA;
cur2=headB;
if(size2>size1)
{
swap(cur1,cur2);
swap(size1,size2);
}//使A链表为最长的那条
int gap=size1-size2;
while(gap--)
{
cur1=cur1->next;
}//cur1cur2对齐
while(cur1!=NULL)
{
if(cur1==cur2)
{
return cur1;
}
cur1=cur1->next;
cur2=cur2->next;
}
return NULL;
}
};
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode*fast=head;
ListNode*slow=head;
while(fast!=NULL&&fast->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;//快指针相对于慢指针一步一步走,所以不会跳格
if(slow==fast)//快慢指针相遇
{
ListNode*index1=head;
ListNode*index2=fast;
while(index1!=index2)
{
index1=index1->next;
index2=index2->next;
}
return index1;
}
}
return NULL;
}
};
注意点1: while(fast!=NULL&&fast->next!=NULL)
快指针为两步两步跳,所以需要判断fast->next!=NULL
2.在推理过程中,大家可能有一个疑问就是:为什么第一次在环中相遇,slow的 步数 是 x+y 而不是 x + 若干环的长度 + y 呢? 3.为什么快指针一定能追上慢指针,不会跳过呢?原因:慢指针一步一步走,快指针两步两步走,快指针相对于慢指针每单位之间只是多走一步,所以一定能追上。