打卡第四天,因为科三前几天没有带电脑,现在重新补一下第四天的卡
今日任务
- 24. 两两交换链表中的节点
- 19.删除链表的倒数第N个节点
- 面试题 02.07. 链表相交
- 142.环形链表II
24. 两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
解题
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* newHead = new ListNode(0);
newHead->next = head;
ListNode *cur = newHead;
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;
}
return newHead->next;
}
};
19.删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
解题
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *newHead = new ListNode(0);
newHead->next = head;
ListNode *fast = newHead, *slow = newHead;
while(n--) fast = fast->next;
fast = fast->next;
while(fast != NULL) {
slow = slow->next;
fast = fast->next;
}
slow->next = slow->next->next;
return newHead->next;
}
};
删除倒数第n个节点,因为链表不能随机访问,所以想要找到第 n 个节点,需要先循环遍历链表,求出节点个数 len,然后再循环遍历链表 len - n - 1 就找到了倒数第 n 个结点的前一个结点,然后就可以删除了。
但我们可以弄两个指针,fast,low,相隔 n + 1 个结点,两个指针每次都是移动一个单位, 当 fast 到达链表尾,slow 指向倒数第 n 个结点 的前一个结点,就可以删除第n 的结点了。
面试题 02.07. 链表相交
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例 2:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例 3:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
我的解题
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(!headA || !headB) return nullptr;
ListNode* pA = headA, *pB = headB;
while(pA != pB){
if(pA == nullptr) pA = headB;
else pA = pA->next;
if(pB == nullptr) pB = headA;
else pB = pB->next;
}
return pA;
}
};
之前做过这道题,两个指针同时分别交替遍历两个链表,一个从先遍历 A再遍历 B,另一个反过来,最终同时指向 null,lenA + lenB值不变,所以无论从哪一个链表开始遍历,最终会同时遍历完两链表,同时指向 null。
相交的链表,同理,两指针会同时间指向相交的结点,向 pA 走了11步,pB 也是一样11步就到 相交的结点。
题解步骤:
先定义两个指针,一个指向 A 链表的头结点 pA。
当 pA为空之后,指向 B 链表的头结点 pB;当 pB为空之后,指向 A 链表的头结点 pA
直到两个指针相等,如果指针为空说明链表没有相交,如果指针不为空,说明链表相交。
代码随想录
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *curA = headA, *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;
if(lenA < lenB) {
swap(lenA, lenB);
swap(curA, curB);
}
int n = lenA - lenB;
while(n--) {
curA = curA->next;
}
while(curA != NULL && curB != NULL) {
if(curA == curB) return curA;
curA = curA->next;
curB = curB->next;
}
return nullptr;
}
};
让 curA 移动到,和 curB 头对齐的位置,如
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
否则循环退出返回空指针。
142.环形链表II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
我的解题
看了卡哥题解之后大概懂了。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head, *slow = head;
do{
if(fast == NULL || fast->next == NULL) return nullptr;
fast = fast->next->next;
slow = slow->next;
} while(fast != slow);
ListNode *item1 = head, *item2 = fast;
while(item1 != item2) {
item1 = item1->next;
item2 = item2->next;
}
return item1;
}
};