题目
来源:JZ22 链表中倒数最后k个结点
描述
输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。
如果该链表长度小于k,请返回一个长度为 0 的链表。
数据范围:0≤n≤10^5 ,0≤ai≤10^9 ,0≤k≤10^9
要求:空间复杂度 O(n),时间复杂度 O(n)
进阶:空间复杂度 O(1),时间复杂度 O(n)
例如输入{1,2,3,4,5},2时,对应的链表结构如下图所示:
其中蓝色部分为该链表的最后2个结点,所以返回倒数第2个结点(也即结点值为4的结点)即可,系统会打印后面所有的节点来比较。
示例1
输入:
{1,2,3,4,5},2
返回值:
{4,5}
说明:
返回倒数第2个节点4,系统会打印后面所有的节点来比较。
示例2
输入:
{2},8
返回值:
{}
解析
方法一:倒数第k个节点,反过来就是正数第n-k+1个节点,所以只需扫描一遍链表得到总节点数n,然后指针从头节点开始走n-k次即可,注意k可能大于n,此时要返回空指针。
ListNode* FindKthToTail(ListNode* pHead, int k) {
int n = 0;
ListNode*p = pHead;
while (p) {
n++;
p = p->next;
}
if (k > n)return NULL;
p = pHead;
for (int i = 1; i <= n - k; i++)
p = p->next;
return p;
}
方法二:快慢指针法,定义快指针先走k个节点,慢指针从头节点开始走,当快指针为空时,慢指针所在即倒数第k个节点,这里也要注意k>n的情况,很好处理,见代码
ListNode* FindKthToTail(ListNode* pHead, int k) {
ListNode*slow = pHead, *fast = pHead;
while (fast && k) {
fast = fast->next;
k--;
}
if (k > 0)return NULL;
while (fast) {
fast = fast->next;
slow = slow->next;
}
return slow;
}