Leetcode 24 两两交换链表中的节点
题目链接 两两交换链表中的节点
本题还是对链表基础操作的考察,只不过进行了变形,还有些需要注意的点的;
首先是要对while中终止条件的思考,其次在交换节点时,注意顺序和对节点的数据进行提前记录,方便以后遍历。
下面直接用代码加注释的形式展现给大家:
/**
* 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*dunnyhead = new ListNode(0);//定义一个虚拟头
dunnyhead->next = head;//连接在head前
ListNode*cur = dunnyhead;//cur指向虚拟头文件
while(cur->next!=NULL&&cur->next->next!=NULL){//偶数时,满足第一个条件即可,奇数时,满足另一个条件即可
//两个节点的值会改变,所以要将这两个节点值提前记录下来
ListNode*temp = cur->next;
ListNode*temp1 = cur->next->next->next;
cur->next = cur->next->next;//dunnyhead和数字2连接起来
cur->next->next = temp;//此时需要将数字2连接到数字1上,数字二现在是1节点,数字1变成了二节点
temp->next = temp1;//数字1连接到数字3上即可
cur = cur->next->next;//需要移动cur指针到第二个节点,为了方便后面的继续遍历和交换节点
}
return dunnyhead->next;//首节点
}
};
Leetcode 19 删除链表的倒数第 N 个结点
题目链接19 删除链表的倒数第 N 个结点
本题目还是需要技巧,首先我们要删除倒数第n个节点,我们就要想到两个条件,第一个条件就是需要将指针指向删除节点的前一个,这样方便删除倒数第n个节点,第二个条件就是while停止条件是什么,解决这两个问题后本问题就很简单了,对于第一个问题,我们首先需要一个fast指针和一个slow指针,让fast先走n+1步,随后让slow和fast同时再走,当fast==NULL,你会发现slow指针刚好指在需要删除节点的上一位,很奇妙!画个图理解一下:
下面是代码和注释:
/**
* 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*dunnyhead = new ListNode(0);//虚拟头节点
dunnyhead->next = head;//建在head的前面
ListNode*slow = dunnyhead;//快慢指针都放到虚拟头节点上
ListNode*fast = dunnyhead;
n++;//这里比较难想,首先第一个while是先让fast指针先走n+1步;
//为了使slow指针指向需要删除节点的前一位,这样方便后续将删除节点删掉
while(n--&&fast!=NULL){
fast = fast->next;//遍历,让fast走n+1步
}
while(fast!=NULL){//当fast指向空时,说明此时slow已经走到删除节点的前一位了
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;//删除节点
return dunnyhead->next;//结束
}
};
Leetcode 面试题 02.07. 链表相交
题目链接 面试题 02.07. 链表相交
本题要审好题目,审准题目就解决问题了
再说一下做题的思路:
把两个链表的节点数算出,记录下两个链表的节点数差,这是为了让两个链接的指针保持到同一节点上,让两指针同时移动,直到移动到相同节点(数据)时就返回指针所指到的节点,否则就返回NULL
下面是代码加注释:
/**
* 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 asize = 0;//节点数
int bsize = 0;
int csize = 0;//节点数差
while(curA!=NULL){
curA = curA->next;//计算a节点数
asize++;
}
while(curB!=NULL){
curB = curB->next;//计算b节点数
bsize++;
}
curA = headA;//此时cur已经指向了节点末尾,要更新一下,将cur调到head
curB = headB;
if(bsize>asize){//这里是讨论到链表谁长的问题,要把长的放在前面
swap(asize,bsize);
swap(curA,curB);
}
csize = asize-bsize;
while(csize--){//将长链表的指针调到和短链表的指针的同位置
curA = curA->next;
}
while(curA!=NULL){//同时移动
if(curA==curB){//节点相同返回该节点
return curA;
}
curA = curA->next;//遍历
curB = curB->next;
}
return NULL;
}
};
Leetcode 142. 环形链表 II
题目链接 142 环形链表 II
本题目考察的不只是对环行链表的判断,还有对数学只是的一些渗透,基本的思想还是双指针,利用快慢指针来解决问题。首先我们需要判断是否为环链表,如何判断,我来解释一下:我们让fast指针每次移动两个节点,slow每次移动一个节点,同时从head开始移动,若不为环,slow指针永远追不到fast指针,若为环,结果两指针一定重合,原因是因为,fast相对于slow的速度为1,若两指针都在闭环中,相当于fast以每次一个节点的速度在靠近slow指针,重合时即证明了该链表是环链表。这是第一个问题,第二个问题就比较考验数学思维了,我们如何求环链表的入口节点,我用画图的形式来解释一下这个问题:
(图画的很丑,勿喷哈哈)
这个问题就解决了,但是还有一些分歧,就是slow指针应该是2(x+y)+k(y+z){k为圈数},为什么不会有这种情况呢,因为当slow走了一圈时,fast已经走了两圈了,因为fast在环内追slow时相对速度是1,就不存在slow走了一圈,fast走两圈才相遇到的情况,只有fast走一圈,在环内追,刚进入环的slow的这一种情况。下面画个简图给大家看一下:
下面是代码加注释:
/**
* 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 = head;//定义一个快指针,每次走两个节点
ListNode*slow = head;//慢指针,每次走一个节点
ListNode*index1 = fast;//index1,index2是为了判断环链表的入口
ListNode*index2 = head;
while(fast!=NULL&&fast->next!=NULL){//首先要保证在快指针移动下,找不到最后的一个节点,即证明是环的一个前提条件,也防止了空指针
fast = fast->next->next;//fast走两步
slow = slow->next;//slow走一步
if(slow==fast){//如果两节点相遇,这是就已经证明了是环了
//下面来求环链表的入口
index1 = fast;
index2 = head;
while(index1!=index2){//这里可以看上面的公式理解
index1 = index1->next;
index2 = index2->next;
}
return index1;//返回入口值
}
}
return NULL;//否则返回空
}
};
不早了,end