剑指offer14_链表中倒数第k个结点_题解
链表中倒数第k个结点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
分析
方案一:快慢指针
使用快慢指针,首先让快指针先行k步,然后让快慢指针每次同行一步,直到快指针指向空节点,慢指针就是倒数第K个节点。
参考链接:
/**
时间复杂度:O(n)
空间复杂度:O(1)
**/
class Solution {
public:
// 快慢指针
ListNode *FindKthToTail(ListNode *pListHead, unsigned int k)
{
// 特判头结点为空和k<=0的情况
if (!pListHead || k <= 0)
return NULL;
ListNode *p = pListHead, *q = p;
//快指针q先行k步
while (k--)
{
if (q != NULL)
q = q->next;
else
return NULL;
}
// 快慢指针同行直到快指针q指向空节点
while (q != NULL)
{
p = p->next;
q = q->next;
}
// 返回慢指针即倒数第k个节点
return p;
}
};
方案二:求链表倒数第 \(k\) 个节点转换为求正数第 \(n-k\) 个节点
假设有\(5\) 个节点,序号 \(1\) 表示第 \(1\) 个节点,假设求倒数第 \(k\) 个,那么正数就应该是从头结点开始往后推\((n-k)\) 个,\(n\) 代表所有节点的个数(不包含空节点),也可以说 \(n\) 代表指针的个数
下图中 \(n=5,k=2\),所以需要从头结点往后经过 \(n-k=5-2=3\) 个指针
/**
时间复杂度:O(n)
空间复杂度:O(1)
**/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
// 特判头结点为空和k<=0的情况
if(!pListHead || k <= 0) return NULL;
int len = 0;
ListNode* p = pListHead;
//计算链表长度len
while(p != NULL){
p = p->next;
++len;
}
// 特判k>len的情况
if(len < k) return NULL;
len -= k;//求链表倒数第k个节点转换为求正数第n-k个节点
// 从头结点往后数n-k个节点
while(len--){
pListHead = pListHead->next;
}
return pListHead;
}
};