代码随想录代码随想录【day 4】| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点 、 面试题 02.07. 链表相交、142.环形链表II
24. 两两交换链表中的节点
题目链接:24.两两交换链表中的节点
卡尔文解
视频讲解
题目描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
解题思路及注意事项:
- 使用虚拟头节点
- cur 指针总是指向两两被交换节点的,第一个节点之前,即下图的 cur。
- 初始时,current 指向虚拟头结点,然后进行如下三步:
- 遍历结束条件:
a. 偶数个数节点数目: cur->next== NULL
b. 奇数个数节点数目:cur->next->next == NULL - 注意在交换指针之前,保存之前指针指向。
代码实现:
/**
* 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 *dummy_head = new ListNode( -9999, head );
ListNode *crt = dummy_head;
ListNode *tmp1, *tmp2;
// Determine if should stop travelling.
// 1. crt->next == NULL for travelling at the end of even Listnode numbers.
// 2. crt->next->next == NULL for travelling at the end of odd node number.
while (crt->next != NULL && crt->next->next != NULL){
tmp1 = crt->next;
tmp2 = crt->next->next->next;
crt->next = crt->next->next;
crt->next->next = tmp1;
tmp1->next = tmp2;
crt = crt->next->next;
}
return dummy_head->next;
}
};
19.删除链表的倒数第N个节点
题目链接:19.删除链表的倒数第N个节点
卡尔文解
视频讲解
题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。。
解题思路及注意事项:
- 按照常规:定义一个虚拟头节点。
- 定义两个 fast and slow 指针 which 指向头结点。
- Fast 要比 Slow 快 n + 1 步,使得slow 指向要删除节点的前一个节点。
- 按照常规操作删除需要删除的节点:slow->next = slow->next->next;
代码实现:
/**
* 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 *dummy_head = new ListNode(-999, head);
ListNode *fast = dummy_head;
ListNode *slow = dummy_head;
n++;
while (n-- && fast != NULL){
fast = fast->next;
}
while( fast ){
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummy_head->next;
}
};
707. 面试题 02.07. 链表相交
解题思路重点:
- 先计算出 2 个链表的长度。
- 求出两个链表长度的差值,然后让 curA 移动到,和 curB 末尾对齐的位置
- 此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
代码实现:
/**
* 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 *crt_A = headA;
ListNode *crt_B = headB;
//Calculate each len of List.
int len_A = 0;
int len_B = 0;
while( crt_A != NULL ){
crt_A = crt_A->next;
len_A++;
}
while( crt_B != NULL ){
crt_B = crt_B->next;
len_B++;
}
crt_A = headA;
crt_B = headB;
if( len_B > len_A ){
swap( len_A, len_B);
swap( crt_A, crt_B);
}
int diff = len_A - len_B;
while( diff-- ){
crt_A = crt_A->next;
}
while( crt_A != NULL ){
if( crt_A == crt_B ){
return crt_A;
}
crt_A = crt_A->next;
crt_B = crt_B->next;
}
return NULL;
}
};
142.环形链表II
解题思路重点:
- 快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 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 *slow = head;
ListNode *fast = head;
bool found = false;
while(( fast != NULL) && ( fast->next != NULL )){
slow = slow->next;
fast = fast->next->next;
if( slow == fast ){
found = true;
break;
}
}
if( found ){
fast = head;
while( fast != slow ){
fast = fast->next;
slow = slow->next;
}
return slow;
}
return NULL;
}
};