● 24. 两两交换链表中的节点
题目链接:力扣题目链接
文章链接:代码随想录 (programmercarl.com)
视频链接:帮你把链表细节学清楚! | LeetCode:24. 两两交换链表中的节点
这道题要求不修改节点内部的值,那就是纯粹交换整个节点的位置,换句话说就是
改变节点的连接顺序
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyhead=new ListNode(0,head);
ListNode* cur=dummyhead;
while(cur->next!=NULL&&cur->next->next!=NULL)
{
ListNode* tmp1=cur->next;//tmp1也保存节点位置
ListNode* tmp2=cur->next->next->next;//tmp2也保存节点位置
cur->next=cur->next->next;
cur->next->next=tmp1;
cur->next->next->next=tmp2;
cur=cur->next->next;//两两交换一次,所以要跳过一个节点
}
return dummyhead->next;
}
};
19.删除链表的倒数第N个节点
题目链接:力扣题目链接
文章链接:代码随想录 (programmercarl.com)
视频链接:链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点
首先,我的第一想法是把找倒数第几个节点的问题转变为顺序第几个节点的问题,所以先通过遍历,找到所有节点的个数,相减求正序,接着再移除节点,代码如下:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead=new ListNode(0,head);
ListNode* cur=dummyhead;
int len=-1;
int m;
while(cur!=NULL)
{
len++;
cur=cur->next;
}
m=len-n;
cur=dummyhead;
for(m;m>0;m--)
{
cur=cur->next;
}
ListNode* tmp=cur->next;
cur->next=cur->next->next;
delete tmp;
return dummyhead->next;
}
};
当然,这道题还可以用双指针来做
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead=new ListNode(0,head);
ListNode* fast=dummyhead;
ListNode* slow=dummyhead;
while((n--)>=0 && fast != NULL)//fast先走n+1步
{
fast = fast->next;
}
while(fast!=NULL)
{
fast=fast->next;
slow=slow->next;
}
ListNode* tmp=slow->next;
slow->next=slow->next->next;
delete tmp;
return dummyhead->next;
}
};
其实,双指针法的思路和第一种相似,只是将倒数的步数提前让fast全走掉了,剩下的就是顺序走的步数。
面试题 02.07. 链表相交
题目链接:力扣题目链接
文章链接:代码随想录 (programmercarl.com)
此题须注意题目要求,找到链表相交的起始节点,也就是相等的不只是节点的val,而是整个节点,并且交点后所有节点都相交,说明了,交点及交点后节点数量相同, 那就让节点多的链表先走他们节点差值的步数,再判断节点是否相等,代码如下:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode*cura=headA;
ListNode*curb=headB;
int len_a=0,len_b=0;
while(cura!=NULL)
{
cura=cura->next;
len_a++;
}
while(curb!=NULL)
{
curb=curb->next;
len_b++;
}
cura=headA;
curb=headB;
if(len_a>=len_b)
{
int n=len_a-len_b;
while(n--)
{
cura=cura->next;
}
while(cura!=curb)
{
cura=cura->next;
curb=curb->next;
}
return cura;
}
if(len_a<len_b)
{
int n=len_b-len_a;
while(n--)
{
curb=curb->next;
}
while(cura!=curb)
{
cura=cura->next;
curb=curb->next;
}
return cura;
}
return NULL;
}
};
142.环形链表II
题目链接:力扣题目链接
文章链接:代码随想录 (programmercarl.com)
视频链接:把环形链表讲清楚!| LeetCode:142.环形链表II
先附上代码:
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 index2;
}
}
return NULL;
}
};
首先,fast每走两步,slow就走一步,相对的就是slow原地不动,fast走一步,在一个环形“赛道”上,fast一定能与slow相遇,来证明链表有环。
浅浅盗一下卡哥的图。。。。
如何判定入口呢?
x+y+n*(y+z)=2*(x+y)=>x=n*(y+z)-y=>x=(n-1)*(y+z)+z--------等于条件fast走的节点个数是slow的两倍
通过公式就可以看出,假如两个指针,一个在头结点,一个在相遇点,都是速度1,他们一定会在入口点相遇。
Day4 打卡成功,耗时4小时。