题目
输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。
如果该链表长度小于k,请返回一个长度为 0 的链表。
数据范围:0≤n≤$105,0≤ai≤109,0≤k≤109
要求:空间复杂度 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步,然后慢指针再从头开始,这个时候这两个指针同时移动,当快指针到链表的末尾的时候,返回慢指针即可。
需要注意边界条件。
解答代码
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* @param pHead ListNode类
* @param k int整型
* @return ListNode类
*/
ListNode* FindKthToTail(ListNode* pHead, int k) {
// write code here
if (pHead == nullptr || k == 0) {
return nullptr;
}
auto slow = pHead;
auto fast = pHead;
while (fast != nullptr) {
if (k > 0) {
// 先将fast移动k位
fast = fast->next;
k--;
} else {
// 再一步一步移动slow和fast
slow = slow->next;
fast = fast->next;
}
}
if (k > 0) {
// 注意边界条件,k大于链表大小
return nullptr;
}
// 返回slow
return slow;
}
};