两两交换链表中的节点:
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
对应力扣24题
这题简单,使用虚拟头结点,然后用两个临时指针,一个固定指针就行,画图可以看的很清楚
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* vhead=new ListNode();
vhead->next=head;
ListNode* cur=vhead;
while(cur->next!=NULL&&cur->next->next!=NULL)
{ ListNode* temp=cur->next;
ListNode* temp1=cur->next->next->next;
cur->next=cur->next->next;
cur->next->next=temp;
temp->next=temp1;
cur=temp;
}
return vhead->next;
}
};
删除链表的倒数第N个节点:
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
对应力扣19题
说实话,如果支持多次扫描的话,确实很简单,可以手搓,但是扫描一次的话可能有点难
手搓代码,直接先遍历一遍得到链表的大小,然后再删除:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
int i=0;
ListNode* vhead=new ListNode();
vhead->next=head;
ListNode* flag=vhead;
if(vhead->next==NULL)return head;
while(flag->next!=NULL)
{ i++;
flag=flag->next;
}
ListNode* flag1=vhead;
for(int j=0;j<i-n;j++)
{ flag1=flag1->next;
}
ListNode* temp=flag1->next;
flag1->next= flag1->next->next;
delete temp;
return vhead->next;
}
};
巧妙方法使用双指针:
如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了,因为slow要指向被删除的结点,所有应该让fast走n+1步。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* vhead=new ListNode();
vhead->next=head;
n++;
ListNode* fast=vhead;
ListNode* slow=vhead;
while(n--&&fast!=NULL)
{
fast=fast->next;
}
while(fast!=NULL)
{
fast=fast->next;
slow=slow->next;
}
ListNode* temp=slow->next;
slow->next=slow->next->next;
delete temp;
return vhead->next;
}
};
链表相交:
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
对应力扣160题
这题解法太妙了,
我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* flag1=headA;
ListNode* flag2=headB;
int len_A=0;
int len_B=0;
while(flag1!=NULL)
{
len_A++;
flag1=flag1->next;
}
while(flag2!=NULL)
{
len_B++;
flag2=flag2->next;
}
flag1=headA;
flag2=headB;
if(len_A<len_B)
{
swap(len_A,len_B);
swap(flag1,flag2);
}
int n=len_A-len_B;
while(n--)
{
flag1=flag1->next;
}
while(flag1&&flag2)
{
if(flag1==flag2)
return flag1;
flag1=flag1->next;
flag2=flag2->next;
}
return NULL;
}
};
环形链表II:
题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
纯纯数学题,没啥好说的,对应力扣142题。
把环形链表讲清楚! 如何判断环形链表?如何找到环形链表的入口? LeetCode:142.环形链表II_哔哩哔哩_bilibili
这里是讲解。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast=head;
ListNode *slow=head;
while(fast!=NULL&&fast->next!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
{ ListNode *index1=fast;
ListNode *index2=head;
while(index1!=index2)
{ index1=index1->next;
index2=index2->next;
}
return index1;
}
}
return NULL;
}
};
哦对了,明天休息