写在前面:
进行链表操作的题,大部分加上虚拟头指针都比较好理解加解题。
链表的题要多画图,增强理解
704.答题过程
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//创建虚拟头结点
ListNode* dummyHead=new ListNode(0);
dummyHead->next=head;
ListNode* cur=dummyHead;
//这里的while条件需要留意一下,()里面是满足条件 进行循环
while(cur->next!=nullptr&&cur->next->next!=nullptr){//这里的两个条件分别对应的是奇函数和偶函数的终止条件,!=的时候才能进入while循环,注意这里顺序不能错,因为如果把cur->next->next放在前面的话,如果cur->next已经是空,那么在判断cur->next->next时候已经没有意义,就会出现空指针异常
ListNode* tmp;//创建暂存结点
ListNode* tmp1;//再创建一个暂存结点用来存储交换后的第一个结点
tmp=cur->next;//先把cur->next暂存起来
tmp1=cur->next->next->next; //存储cur->next->next->next的空间
//下面进行交换操作,在纸上画出来过程比较好理解
cur->next=cur->next->next;
cur->next->next=tmp;
cur->next->next->next=tmp1;
cur=cur->next->next; //cur移动两位,准备下一轮交换
}
head=dummyHead->next;
delete dummyHead;
return head;
}
};
19.答题过程
自己先写了个答案 单指针:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
//创建虚拟头结点
ListNode* dummy=new ListNode(0);
dummy->next=head;
//采用指针,先创建一个指针让他找到最后一个结点,得到有链表中有几个结点
int number=0;//number是指链表中的结点数量
ListNode* cur=dummy;
while(cur->next!=nullptr){
cur=cur->next;
number++;
}
//接下来找到链表中倒数第n个结点前面的一个结点让其为tmp
ListNode* tmp=dummy;
int c=0;//c的目的就是用来实现找到链表倒数第n+1个结点的
while(c<number-n){
tmp=tmp->next;
c++;
}
//进行删除结点操作
tmp->next=tmp->next->next;
return dummy->next;
}
};
双指针:
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!=nullptr){//先让fast走n步,注意n--是先用n运算再--,因为while是n=0终止!不是n<0!!所以这里是走了n步,不是n+1步
fast=fast->next;
}
fast=fast->next;//这里让fast再多走一步,让其比slow多走了n+1步!
while(fast!=nullptr){//让fast和slow一起前进,因为fast先走了n+1步,那么当fast指向nullptr时候,slow指向的是倒数第n个指针的前一个指针
fast=fast->next;
slow=slow->next;
}
//用slow指针进行删除操作
slow->next=slow->next->next;
return dummyHead->next;
}
};
面试题 02.07. 链表相交 答题过程
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和curB恢复!!!
curA=headA;
curB=headB;
//比较一下两个链表的长度
if(lenA<lenB){//目的是让curA为最长链表的头,lenA为其长度,因为这里没有说返回的A和B必须是原来的,所以可以进行这样的操作
swap(curA,curB);//链表也可以用swap操作进行交换
swap(lenA,lenB);
}
//求长度差
int gap=lenA-lenB;
//让curA和curB在同一起点上(末尾位置对齐),因为多的那部分肯定是没有交点的
while(gap--){//即让curA先前进gap
curA=curA->next;
}
//这样就可以开始遍历curA 找交点,如果找到交点直接return,如果到curA=NULL还没有的话 return NULL(题目要求)
while(curA!=NULL){
if(curA==curB){
return curA;
}
curA=curA->next;
curB=curB->next;
}
return NULL;
}
};
142.答题过程
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
//定义一个快指针,定义一个慢指针
ListNode* fast=head;
ListNode* slow=head;
while(fast!=NULL&&fast->next!=NULL){
slow=slow->next;//设慢指针是一步一步走的,速度为1
fast=fast->next->next;//设快指针是两步两步走的,速度为2
if(slow==fast){//如果快慢指针相遇,那么证明一定存在环
ListNode* Index1=slow;//定义快慢指针在环内相遇的点为Index1
ListNode* Index2=head;//这里定义一个Index2从头结点开始
//让Index1和Index2都设为一步一步走(速度为1)
while(Index1!=Index2){//当这两个指针相遇时,就是环开始的点。————这里不懂需要看视频或者自己画一下,列一下等式(这种思考方式就是数据结构)
Index1=Index1->next;//让这两个指针一步一步走,直到相等
Index2=Index2->next;
}
return Index1;//放回环开始的结点
}
}
return NULL;//表示链表无环
}
};