leetcode链接:https://leetcode.cn/problems/swap-nodes-in-pairs/
视频链接:帮你把链表细节学清楚! | LeetCode:24. 两两交换链表中的节点 (opens new window)
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
跟之前的翻转链表比较相似,关键点都是创建虚拟头节点、以及保存tmp指针:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* cur = dummy;
while(cur->next != nullptr && cur->next->next != nullptr){
ListNode* tmp1 = cur->next;//1
ListNode* tmp2 = cur->next->next->next;//3
cur->next = cur->next->next;//第一步
cur->next->next = tmp1;//第二步
tmp1->next = tmp2;//第三步
cur = cur->next->next;//移动cur
}
return dummy->next;
}
};
这里的while(cur->next != nullptr && cur->next->next != nullptr){
看似是冗余的,只要next为空,next->next肯定是空的了,但这考虑了head就为NULL的情况以及防止访问next->next是空指针。
leetcode链接:力扣题目链接(opens new window)
视频链接:链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点 (opens new window)
本题一刷的时候,只有暴力思路,比如先遍历一次链表求出长度,再正序删除第m-n个节点,很明显这不是最优解。后来看完视频后,二刷直接就有了思路,也很幸运的直接ac了。实质就是双指针那一套,快指针先走n步,然后快慢指针同时走,知道快指针到底,此时快指针走了m-n步,慢指针也走了m-n步,正好停在要删除节点的前面。
以下摘自代码随想录:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9xybvPHv-1689493489043)(https://code-thinking.cdn.bcebos.com/pics/19.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B9.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LZmXjEeJ-1689493489044)(https://code-thinking.cdn.bcebos.com/pics/19.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B91.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nIBp2wcF-1689493489044)(https://code-thinking.cdn.bcebos.com/pics/19.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B92.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wyWw9jZI-1689493489045)(https://code-thinking.cdn.bcebos.com/pics/19.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B93.png)]
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* fast = dummy;
ListNode* slow = dummy;
while(n--){
fast = fast->next;
}
while(fast->next != nullptr){
fast = fast->next;
slow = slow->next;
}//结束后slow停在要删除节点的前一个位置
// cout<< slow->next->val;
ListNode* tmp = slow->next;
slow->next = tmp->next;
delete tmp;
return dummy->next;
}
};
leetcode链接:力扣题目链接(opens new window)
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
这里的注意点是值相同不一定等于相交,应该是两个节点的指针相同。
这道题是一刷,只想到暴力解法,两个for循环,一个一个比较,后来看了题解才做出来。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lengthA = 0, lengthB = 0;
while(curA != nullptr){
lengthA++;
curA = curA->next;
}
while(curB != nullptr){
lengthB++;
curB = curB->next;
}
//这里要重新开始遍历,要对curA curB进行重新赋值
curA = headA;
curB = headB;
//假设A为短的链表,B为长的链表
if(lengthA > lengthB){
swap(lengthA,lengthB);
swap(curA,curB);
}
int gap = lengthB - lengthA;
while(gap--){
curB = curB->next;
}
while(curA != nullptr){
if(curA == curB){
return curA;
}
curA = curA->next;
curB = curB->next;
}
return nullptr;
}
};
leetcode链接:力扣题目链接(opens new window)
视频链接:把环形链表讲清楚!| LeetCode:142.环形链表II (opens new window)
这题是二刷了, 当时一刷就云里雾里了,二刷首先想到了方法,知道怎么判断是否有环了,但怎么求环的入口还是转不过来。总结一下就是快慢指针,如果有环那么一定能相遇。重点是怎么求环的入口:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while(fast != nullptr && fast->next != nullptr){
fast = fast->next->next;
slow = slow->next;
if(fast == slow) {//说明有环
slow = head;
while(slow != fast){
slow = slow->next;
fast = fast->next;
}
return slow;
}
}
return nullptr;
}
};
链表章节的题目刷完了,大部分二刷都有思路,但通过几次才能AC,总的来说难度不大,环形列表可能求入口的时候有点难以理解。