开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 14 天,点击查看活动详情
Day42 2023/02/17
难度:简单
题目
思路
本题可以采用双指针的方式,即一快一慢两个指针,我们知道从倒数第k个节点(包括自身)出发一直到最后一个节点一共有k个节点(包括最后一个节点),所以如果有两个指针,一开始就相差k个节点,呢么当两个指针同时移动,其中一个指针指向最后一个节点时,这时另一个指针就指向目标节点了。
具体步骤:
- 一开始上fast指针向行k步。
- 然后fast和slow指针同时出发,当fast指向表尾指针的下一个节点,slow指针就指向了目标节点。
- 返回目标节点的值。
关键点
- 这里fast指针最后没有指向尾节点,而是在向后走了一个步,是为了slow指针在多走一步正好指向目标节点,不然就指向了前驱节点。但如果题目要求是删除倒数第k个节点的话就可以这样方便找到前驱节点进行删除操作。
算法实现
c++代码实现-双指针法
#include <iostream>
using namespace std;
//定义单链表
struct LNode {
int val;
LNode *next;
LNode(int x) : val(x), next(nullptr){};
};
//返回链表倒数第K个节点
int FindKToTail(LNode *head, int k) {
LNode *fast = head,
*slow = head; //快慢指针一开始都指向逻辑上的头节点
//先让fast指针先走k步
while (k--) {
if (!fast)
break; // k值非法输入(k > n)
fast = fast->next;
}
// fast,slow指针同时出发
while (fast) {
fast = fast->next;
slow = slow->next;
} //循环结束slow正好指向倒数第k个节点
return slow->val;
}
int main() {
//测试以下
//手动创建一个链表1->2->3
LNode *head = new LNode(1), *second = new LNode(2), *third = new LNode(3);
head->next = second;
second->next = third;
int res = FindKToTail(head, 1); //返回倒数第三个节点的值,即1
cout << "结果为:" << res;
return 0;
}
- 时间复杂度 --- fast和slow一起访问了全部节点,其中n为节点个数
- 空间复杂度 --- 链表为必要空间,无额外辅助空间
总结
碰到数组,链表这一类与之类似的题目,都可以考虑以下双指针的方法