链表中倒数第K个节点
题目:
给定一个头节点为
head
的链表用于记录一系列核心肌群训练项目编号,请查找并返回倒数第cnt
个训练项目编号。示例 1:
输入:head = [2,4,7,8], cnt = 1
输出:8
思路:
使用双指针方法,第一个指针先走cnt步,然后一起走,先走的指针走到末尾,后走的指针走的倒数第cnt第位置。
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* trainingPlan(struct ListNode* head, int cnt)
{
//处理空链表
if(NULL == head)
{
return NULL;
}
struct ListNode* p1 = head;
struct ListNode* p2 = head;
//先让p1走cnt步
for(int i = 0;i < cnt; i++)
{
p1 = p1->next;
}
//p1 和 p2一起走n-cnt步
while(p1 != NULL)
{
p1 = p1->next;
p2 = p2->next;
}
//p1走到末尾,p2到达到倒数cnt的位置
return p2;
}
代码分析:
1. 初始化两个指针
struct ListNode* p1 = head; // 快指针 struct ListNode* p2 = head; // 慢指针
p1
和p2
最初都指向链表头节点head
。2. 快指针
p1
先走cnt
步for (int i = 0; i < cnt; i++) { p1 = p1->next; }
让
p1
向前移动cnt
步,此时p1
和p2
之间相隔cnt
个节点。示例:
链表1 → 2 → 3 → 4 → 5
,cnt = 2
:
p1
移动到3
,p2
仍在1
,两者间隔 2 个节点。3. 同步移动
p1
和p2
while (p1 != NULL) { p1 = p1->next; p2 = p2->next; }
同时移动
p1
和p2
,直到p1
到达链表末尾(NULL
)。此时
p2
会指向倒数第cnt
个节点(因为p1
和p2
始终相隔cnt
步)。4. 返回结果
return p2; // p2 指向倒数第 cnt 个节点
5. 关键点分析
p1
先走cnt
步后,p1
和p2
之间形成固定间隔cnt
。当
p1
走到末尾时,p2
自然落后cnt
步,即倒数第cnt
个节点。