描述
输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。
如果该链表长度小于k,请返回一个长度为 0 的链表。
数据范围:0 ≤n≤10^5,0 ≤ai≤10^9,0 ≤k≤10^9
要求:空间复杂度 O(n),时间复杂度 O(n)
进阶:空间复杂度 O(1)O,时间复杂度 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:
ListNode* FindKthToTail(ListNode* pHead, int k) {
// write code here
//采用双指针法
if(pHead == NULL && k <= 0)
{
return nullptr;
}
//定义fast和slow都指向第一个节点
ListNode* fast = pHead;
ListNode* slow = pHead;
while(k--)
{
//首先让fast遍历k个节点,这样fast和slow就差k个节点
if(fast == nullptr)
{
return nullptr;
}
fast = fast->next;
}
//当fast节点为nullptr时,slow为倒数第k个节点
while(fast != nullptr)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
思路二:数组法
把每个节点装进数组中,访问倒数第 k 个元素。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pHead, int k) {
// write code here
vector<ListNode* > res;
while(pHead)
{
res.push_back(pHead);
pHead = pHead->next;
}
if(res.size() < k)
{
return nullptr;
}
return res[res.size()-k];
}
};