持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情
1、写在前面
大家好,我是翼同学,这里是【水滴计划 | 刷题日志】
每日两题,拒绝摆烂。
2、内容
2.1、题目一:删除链表的倒数第 N 个结点
链接:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
(1) 描述
(2) 举例
(3) 解题
这道题可以利用双指针来求解。
定义快慢指针fast和slow,先让fast移动n步,接着让fast和slow同时移动,直到fast移动到了链表的末尾,此时删掉slow指向的结点,就相当于删掉倒数第n个结点。
演示如下:
结果为:
代码如下:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pHead = new ListNode(0); // 虚拟头结点
pHead->next = head; // 将虚拟头结点指向头指针
ListNode* fast = pHead; // 快指针
ListNode* slow = pHead; // 慢指针
// 让 fast 移动 n 步
while(n-- && fast != NULL) {
fast = fast->next;
}
// fast再移动一步,因为需要让 slow 指向删除节点的上一个节点
fast = fast->next;
// 同时移动快慢指针
while (fast != NULL) {
fast = fast->next;
slow = slow->next;
}
// 删除掉 slow-next
ListNode *tmp = slow->next;
slow->next = tmp->next;
delete tmp;
// 返回运算结果
return pHead->next;
}
};
2.2、题目二:链表相交
链接:面试题 02.07. 链表相交 - 力扣(LeetCode)
(1) 描述
(2) 举例
(3) 解题
第一种解题思路是:
- 定义两个工作指针
curA和curB,分别指向两个链表的头指针 - 接着进入循环(当
curA==curB时退出循环) - 在循环中,指针
curA先遍历链表A,再遍历链表B,curB也一样,先遍历链表B,再遍历链表A - 当指针
curA和curB相等时就可以退出循环,此时直接返回curA即可(如果两个链表没有公共部分,则最后curA和curB会同时指向NULL)
动态示意图如下:
代码如下:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
// 定义两个工作指针
ListNode *curA = headA;
ListNode *curB = headB;
// 循环遍历,当curA==curB时退出循环
while (curA != curB)
{
// 指针 curA 先遍历链表 A ,再遍历链表 B
if(curA != NULL) {
curA = curA->next;
} else {
curA = headB;
}
// 指针 curB 先遍历链表 B ,再遍历链表 A
if(curB != NULL) {
curB = curB->next;
} else {
curB = headA;
}
}
// 返回结果即可
return curA;
}
};
第二种思路:
首先有两个链表:
定义两个工作指针,并分别求出两个链表的长度。此时将两链表的长度之差记录下来。然后将短链表的尾部和长链表对齐。如下所示:
最后我们就可以开始比较两个工作指针是否相同。如果相同,则返回curA即可。否则将两个工作指针同时向后移动一位。
代码如下:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA; // 工作指针 A
ListNode* curB = headB; // 工作指针 B
int lenA = 0; // 链表 A 的长度
int lenB = 0; // 链表 B 的长度
// 求链表A的长度
while (curA != NULL) {
lenA++;
curA = curA->next;
}
// 求链表B的长度
while (curB != NULL) {
lenB++;
curB = curB->next;
}
// 重新定义工作指针的指向
curA = headA;
curB = headB;
// 让 curA 为最长链表的头,lenA为其长度
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
// 求长度差
int len = lenA - lenB;
// 让 curA 和 curB 在同一起点上(末尾位置对齐)
while (len--) {
curA = curA->next;
}
// 遍历 curA 和 curB,遇到相同则直接返回
while (curA != NULL) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
3、写在最后
好了,今天就刷到这里,明天再来。