24. 两两交换链表中的节点
思路:建议使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。最关键的就是要搞清楚指针的指向,操作的先后顺序
操作之后的链表:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead=new ListNode(0);
dummyHead->next=head; //创建虚拟头节点
ListNode* cur=dummyHead;
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;
cur->next->next->next=temp1;
cur=cur->next->next; //往后移动两位 继续交换
}
head=dummyHead->next;
delete dummyHead; //释放虚拟节点
return head;
}
};
19.删除链表的倒数第N个节点
思路:使用虚拟头节点,双指针(不是很明白fast先走n+1)
- 定义fast指针和slow指针,初始值为虚拟头结点
- fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作)
- fast和slow同时移动,直到fast指向末尾
- 删除slow指向的下一个节点(fast指向末尾NULL时,slow刚好在要删除的前面一个节点)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead=new ListNode(0);
dummyHead->next=head;
ListNode* fast=dummyHead; //双指针初始化指向虚拟节点
ListNode* slow=dummyHead;
while(n-- && fast!=NULL){
fast=fast->next;
}
fast=fast->next; //fast指针先向前走n+1步
while(fast!=NULL){
fast=fast->next;
slow=slow->next;
} //fast指针指向NULL时,slow指针指向要删除的节点前一个节点
slow->next=slow->next->next;
return dummyHead->next;
}
};
面试题 02.07. 链表相交
思路:两个链表,找到从哪里开始寻找交点
- curA指向链表A的头结点,curB指向链表B的头结点
- 求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:
- 比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
否则循环退出返回空指针。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA=headA;
ListNode* curB=headB;
int lenA=0,lenB=0; //用来计算两个链表的长度
while(curA !=NULL){
lenA++;
curA=curA->next;
}
while(curB !=NULL){
lenB++;
curB=curB->next;
} //计算两个链表的长度
curA=headA;
curB=headB;
//让curA指向最长链表的头
if(lenB>lenA)
{
swap(lenA,lenB);
swap(curA,curB);
}
int num=lenA-lenB;
//将两个链表在同一个起点上
while (num--) {
curA = curA->next;
}
//遍历 如果遇见相同的 就直接返回相同的交点
while(curA !=NULL){
if(curA==curB){
return curA;
}
curA=curA->next;
curB=curB->next;
}
return NULL;
}
};
142.环形链表II
看不懂,第一次学链表,好难呀,好难呀