题目描述:输入一个链表,输出该链表中倒数第k个结点。
一、一般解法(不够高效)
需要遍历链表两次,第一次统计出链表中结点的个数,第二次才能找到倒数第k个结点。
1.先遍历链表,算出链表节点数count;
2.直接遍历到第count-k个节点;
3.判断链表结点数cout小于k,此时要返回NULL;
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
ListNode* p=pListHead;
int count=0;//遍历得出节点数
while(p!=NULL)//p从第一个开始指向下一个节点,直到指向为NULL时,遍历结束
{
count++;
p=p->next;//得出节点数
}
int number=count-k;//倒数第K个节点就是正数count-k节点的指针
if(number>=0) //即count>=k,保证k的有效
{
while(number)//当number不为空时,进行遍历,找出倒数第k个节点,即正数number个指针
{
pListHead=pListHead->next;//pListHead从头开始指向下一个节点
number--;//从前往后再次搜索
}
}
else//若k大于节点数了,没意义,返回NULL
{
return NULL;
}
return pListHead;
}
};
二、优化解法(推荐)
指定两个指针在链表头,第一个指针先走,走到k-1时,第二个指针也开始走,这样始终保持两个指针距离k-1,当第一个指针走到最后一个节点,此时第二个指针就是倒数第k个节点。
考虑问题全面,提高代码鲁棒性。
1.pListHead指针为空;
2.输入的链表节点数少于k;
3.输入的k为0;
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==NULL||k==0) return NULL;//考虑问题全面,提高代码鲁棒性
ListNode*p=pListHead;//定义p指针从头开始移动
int i=0;
while(i<k-1)//将p移动到k-1位置
{
p=p->next;
if(p==NULL)//说明K超出节点数了
return NULL;
i++;//挺关键的
}
while(p->next)//p->next不为空
{
p=p->next;//p继续后移
pListHead=pListHead->next;//pListHead也从头开始后移
}
return pListHead;//p1->next为空,即p1已在最后一个节点,pListHead就在倒数第k个节点
}
};