学习文章链接:代码随想录
文章目录
一、24. 两两交换链表中的节点
题目链接:24. 两两交换链表中的节点
思路:画图缕清思路。虚拟头节点指针指向第二个节点,第二个节点指针指向第一个节点,第一个节点指向第三个节点。如此循环。
需要注意的点:两节点交换过后要把第二个节点指针指向第三个节点,考虑cur->next->next为非NULL时,也要考虑cur->next非NULL,不然会报错。
方法1:使用虚拟头节点
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummy=new ListNode(0);
dummy->next=head;
ListNode* cur=dummy;
while(cur->next != NULL && cur->next->next!=NULL){
ListNode* temp=cur->next;
ListNode* temp2=cur->next->next->next;
cur->next=cur->next->next;
cur->next->next=temp;
temp->next=temp2;
cur=cur->next->next;
}
return dummy->next;
}
};
方法2:不使用虚拟头节点
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head==NULL||head->next==NULL){
return head;
}
ListNode* temp=head;
ListNode* temp0=head->next->next;
head=head->next;
head->next=temp;
head->next->next=temp0;
ListNode* cur=head->next;
while(cur->next != NULL && cur->next->next!=NULL){
ListNode* temp1=cur->next;
ListNode* temp2=cur->next->next->next;
cur->next=cur->next->next;
cur->next->next=temp1;
temp1->next=temp2;
cur=cur->next->next;
}
return head;
}
};
二、19.删除链表的倒数第N个节点
题目链接:19.删除链表的倒数第N个节点
思路:使用双指针,快指针走n步,然后快慢指针一起走,直到快指针指向尾部,此时慢指针指的即为需要删除的节点。然而要想删除这个节点,slow应该走到前面一个节点停止,然后再将停下的这个节点的指针指向要删除的节点后的节点。
需要注意的点:快指针应该多走一步。
方法1:使用虚拟头节点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy=new ListNode(0);
dummy->next=head;
ListNode* slowindex=dummy;
ListNode* fastindex=dummy;
for(int i=0;i<=n;i++){
fastindex=fastindex->next;
}
while(fastindex!=NULL){
slowindex=slowindex->next;
fastindex=fastindex->next;
}
ListNode* temp=slowindex->next;
slowindex->next=slowindex->next->next;
delete temp;
return dummy->next;
}
};
方法2:不适用虚拟头节点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* slowindex=head;
ListNode* fastindex=head;
for(int i=0;i<n;i++){
fastindex=fastindex->next;
}//画图可知,当快指针走n步走到NULL的时候,说明需要删掉第一个节点,否则的话再走一步
if(fastindex==NULL){
head=head->next;
return head;
}
else{
fastindex=fastindex->next;
}
while(fastindex!=NULL){
slowindex=slowindex->next;
fastindex=fastindex->next;
}
ListNode* temp=slowindex->next;
slowindex->next=slowindex->next->next;
delete temp;
return head;
}
};
三、面试题 02.07. 链表相交
题目链接:面试题 02.07. 链表相交
思路:将两个链表的末端对齐,较长链表先走到两个链表差值的位置,然后同时移动两个链表上的指针,当两个指针相等时,返回这个值,否则返回null;
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *curA=headA;
ListNode *curB=headB;
int lengthA=0;
int lengthB=0;
while(curA!=NULL){
curA=curA->next;
lengthA++;
}
while(curB!=NULL){
curB=curB->next;
lengthB++;
}
curA = headA;
curB = headB;
if(lengthA>=lengthB){
int index=lengthA-lengthB;
while(index--){
curA=curA->next;
}
}
else{
int index=lengthB-lengthA;
while(index--){
curB=curB->next;
}
}
while (curA != NULL && curB != NULL ) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
四、142.环形链表II
题目链接:142.环形链表II
1. 环形链表的原理
1.1 判断是否是环形链表
使用快慢指针,快指针每次走两步,慢指针每次走一步。当链表不是循环链表时,fast一定会先走到NULL,所以只需要判断fast->next是否为NULL就OK。当链表为循环链表时,fast一定先进入环内,当slow进入环内的时候,fast和slow都在环内移动,相对于slow来说,fast每次都移动一步,因此fast和slow一定会在某处相遇,此时跳出循环,判断循环节点。
1.2 判断环形链表的循环节点
考虑从头节点到循环节点的长度x。画图列出式子,然后分类讨论。具体思路参考
2. 环形链表的代码实现
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 *cur=head;
while(cur!=fast){
cur=cur->next;
fast=fast->next;
}
return cur;
}
}
return NULL;
}
};