·用虚拟头结点,这样会方便很多
/**
* 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;//虚拟头结点指向head
ListNode* cur=dummyHead;
while(cur->next!=nullptr&&cur->next->next!=nullptr){
ListNode* tmp=cur->next;//记录临时节点
ListNode* tmp1=cur->next->next->next;//记录临时节点
cur->next=cur->next->next;//步骤一
cur->next->next=tmp;//步骤二
cur->next->next->next=tmp1;//步骤三
cur=cur->next->next;//cur移动两位,准备下一轮交换
}
return dummyHead->next;
}
};
双指针的操作,要注意,删除第N个节点,那么我们当前遍历的指针一定要指向第N个节点的前一个节点(这个题感觉labuladong的代码更好理解)
/**
* 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* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead=new ListNode(0);
dummyHead->next=head;
//删除倒数第n个,要先找到倒数第n+1个节点
ListNode* x=findFromEnd(dummyHead,n+1);
//删掉第n个节点
x->next=x->next->next;
return dummyHead->next;
}
ListNode* findFromEnd(ListNode* head,int k){
ListNode* p1=head;
//p1先走k步
for(int i=0;i<k;i++){
p1=p1->next;
}
ListNode* p2=head;
//p1和p2同时走n-k步
while(p1!=NULL){
p2=p2->next;
p1=p1->next;
}
//p2现在指向第n-k个节点
return p2;
}
};
面试题 02.07. 链表相交
注意数值相同,不代表指针相同
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA=headA;
ListNode* curB=headB;
int lenA=0,lenB=0;
while(curA!=NULL){
curA=curA->next;
lenA++;
}
while(curB!=NULL){
curB=curB->next;
lenB++;
}
curA=headA;
curB=headB;
if(lenA<lenB){
swap(lenA,lenB);
swap(curA,curB);
}
int gap=lenA-lenB;
while(gap--){
curA=curA->next;
}
while(curA!=NULL){
if(curA==curB){
return curA;
}
curA=curA->next;
curB=curB->next;
}
return NULL;
}
};
从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast,*slow;
fast=slow=head;
while(fast!=nullptr&&fast->next!=nullptr){
fast=fast->next->next;//fast一次走两步
slow=slow->next;//slow一次走一步
if(fast==slow) break;
}
//上面的代码类似hashCycle函数
if(fast ==nullptr||fast->next == nullptr){
//fast遇到空指针证明没有环
return nullptr;
}
//重新指向头结点
slow=head;
//快慢指针同步前进,相交点就是换节点
while(slow!=fast){
fast=fast->next;
slow=slow->next;
}
return slow;
}
};