输入一个链表,输出该链表中倒数第k个结点。
题目返回值为指针,首先如何获取到倒数第k的节点的指针呢
方法一:假设整个链表由n个节点,那么倒数第k个节点就是正数第n-k+1个节点,这就容易了。但是要获取到链表的节点的个数就得先遍历一遍链表,然后再遍历一遍获取第n-k+1个节点。一共得遍历两遍链表。
方法二:如何只遍历一遍链表呢?
定义两个指针p和b,先让第一个指针p遍历到正数第k个节点,第二个指针b指向头节点,两个指针相距k-1,然后,然后继续遍历,当p指向最后一个元素时,则b指向倒数第k个元素。
但是这里由很多陷阱,如下面的由缺陷的代码就不具有鲁棒性,有非常多的方式可以使它崩溃:
- 如果输入的是空指针,则代码将访问空指针指向的内存;
- 如果输入的链表节点数小于k,则仍然会因为空指针而崩溃;
- 如果输入的k为0且为无符号整数时,k-1将是个非常大的正整数,程序也会崩溃。
/*
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;
for(int i=0;i<k-1;i++){
p->next!=NULL
p=p->next;
}
ListNode* b=pListHead;
while(p->next!=NULL){
p=p->next;
b=b->next;
}
return b;
}
};
下面是正确的代码
/*
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(k==0||pListHead==NULL) //这个一定不要忘了
return nullptr;
ListNode *p=pListHead;
for(int i=1;i<k;i++){
if(p->next!=NULL) //前进的时候要判断不等于空
p=p->next;
else
return nullptr;
}
ListNode* b=pListHead;
while(p->next!=NULL){
p=p->next;
b=b->next;
}
return b;
}
};