@代码随想录算法训练营第4天 | Leetcode24 两两交换链表的节点, 19 删除链表的倒数第N个节点,面试题 02.07. 链表相交, 142.环形链表II
视频链接:
https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
感觉难点还是在于遍历的时候如何判断cur指针在哪个位置,比如cur是在head节点的时候就需要创建一个tmp存储cur->next->next,然后让cur->next->next指向cur,cur->next指向tmp,然后使用虚拟头结点。
遇到链表问题不清楚的可以画图表示cur的位置,然后寻找while的终止条件以及指针交换的实际操作。
注意创建dummyhead是要new一个新的ListNode。注意交换条件和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* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* cur = dummyhead;
while(cur->next!=nullptr && cur->next->next!=nullptr){
ListNode* tmp = cur->next;
ListNode* ttmp = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = tmp;
cur->next->next->next = ttmp;
cur = tmp;
}
return dummyhead->next;
}
};
30 分钟
https://programmercarl.com/0019.%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.html
用一个while先把链表总长度遍历出来,然后与n求差值得到正着数的No.,然后再用dummyhead加cur的招式即可搞定,就是需要两个循环看起来不聪明的样子,看一下视频的解法。
在dummyhead的基础上结合快慢双指针的技巧,快指针比慢指针多走n+1步,当快指针指向nullptr的时候,慢指针刚好是要删除的node的前一个node。关于实现快指针比慢指针多走了n+1步这个操作还是借助了while循环实现的。
还是要熟练dummyhead的初始化,时刻掌握指针位置。
/**
* 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* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
while(n--){
fast = fast->next;
}
while(fast->next != nullptr){
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummyhead->next;
}
};
20分钟
https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html
只能想到o(m*n的解法,就是循环套循环然后比较地址是否一致)。
先用两个循环分别遍历出A和B链表的长度,然后让两个链表尾尾对齐,开始遍历直到指针相同,因为后面都相同的部分一定是具有比min(len(A), len(B))还要小的长度。
细节还是比较多的,还是要时刻注意curA和curB的位置。然后注意lenA比lenB小的情况下可以采用swap函数把lenA/lenB和curA/curB全部换位置,好让dummyA所代表的永远是最长的链表。详细的参考下面的代码。
/**
* 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* dummyheadA = new ListNode(0);
ListNode* dummyheadB = new ListNode(0);
dummyheadA->next = headA;
dummyheadB->next = headB;
int lenA{0};
int lenB{0};
ListNode* curA = dummyheadA;
ListNode* curB = dummyheadB;
while(curA->next != nullptr){
lenA++;
curA = curA->next;
}
while(curB->next != nullptr){
lenB++;
curB = curB->next;
}
curA = dummyheadA->next;
curB = dummyheadB->next;
if(lenB > lenA){
swap(lenA, lenB);
swap(curA, curB);
}
int gap = lenA - lenB;
while(gap--){
curA = curA->next;
}
while(curA!=nullptr){
if(curA == curB){
return curA;
}
curA = curA->next;
curB = curB->next;
}
return nullptr;
}
};
30 分钟
https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html
没想法。
很巧妙。创建快慢双指针,这次快慢双指针移动的条件很简单,每次快指针移动两个位置,慢指针移动一个位置即可。如果链表中有环,那么快慢指针必定相遇,不然的话快指针走到null。
具体的代码实现还是有点东西需要注意的主要是赋值index1和index2应该都是什么,这里要明确x和z都是怎么定义的x是说走了几步从头到环起点,z是走了几步从fast和slow交点到了环起点,然后y是从环起点走了几步到了交点,所以index1就是slow和fast的交点,而index2应该是dummyhead而不是head。上图也可以模拟出index1和index2的位置,从ab相交位置开始推即可,途中ab就是真实的相交位置(根据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* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
while(fast->next!=nullptr && fast->next->next!=nullptr){
fast = fast->next->next;
slow = slow->next;
if(slow == fast){
ListNode* index1 = slow;
ListNode* index2 = dummyhead;
while(index1!=index2){
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
}
return nullptr;
}
};
40分钟