题目:
输入一个链表,输出该链表中倒数第k个结点。为符合计数习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例子
如:一个链表有6个节点,从头节点开始,它们的值一次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。
链接:
剑指Offer:15题
思路标签:
- 数据结构:链表
- 算法:双指针
- 代码的鲁棒性
解答:
1. C++
- 因为是单向链表,所以无法从后向前遍历;
- 一种直观的思路是先遍历链表得到链表的长度,然后第二次遍历就能找到第k个节点,但是需要进行两次遍历,不是好的方法;
- 这里使用两个指针实现一次遍历,第一个指针先走k-1步,第二个指针一直不动;然后两个指针同时移动,知道第一个指针遍历完成。因为两个指针间隔为k-1,所以第二个指针指向的节点即为倒数第k个节点。
- 需要注意代码的鲁棒性:
- 链表为空;
- k == 0,以为k为无符号整数,k-1=0xFFFFFFFF,导致错误;
- 链表数不够k的情况,也就是第一个指针移动过程中变为nullptr。
/*
struct Listnode
{
int value;
struct Listnode *next
}
*/
class Solution
{
public:
Listnode* FindthToTail(Listnode* pListHead,unsigned int k)
{
if(pListHead=NULL||k==0)
return NULL;
//定义两个指针
Listnode* pAhead = pListHead;
Listnode* pBehind = NULL;
for(unsigned int i=0;i<k-1;i++)
{
if(pAhead->next!=NULL)
pAhead=pAhead->next;
else
return NULL;
}
pBehind=pListHead;
while(pAhead->next!=NULL)
{
pAhead=pAhead->next;
pBehind=pBehind->next;
}
return pBehind;
}
}
}
参考:
《剑指offer》