题目:输入一个链表,输出该链表中倒数第k个结点。
本题考查的是代码的鲁棒性,所谓的鲁棒性是指程序能够判断输入是否合乎规范要求,并对不符合要求的输入予以合理的处理。容错性是鲁棒性的一个重要体现。提高代码鲁棒性的有效途径是进行防御性编程。
思路:首先要判断K值的大小,K的大小为0的话直接返回空,同时K的大小不能超过链表的长度。除此之外,也要注意原始的链表是否为空链表。 如果要求只遍历一次链表:定义两个指针p1和p2,第一个指针从头节点开始往前走k-1步,第二个指针保持不变;从第K步开始,第二个指针也从头节点开始向后遍历。两个指针的距离始终保持在k-1,所以当第一个指针指向最后一个节点时,第二个指针刚好指向倒数第k个指针。
拓展:当 用一个指针遍历链表不能解决问题的时候,可以尝试用两个指针来遍历链表,可以让其中一个指针遍历的速度快一些,或者让它在链表上走若干步。eg:求链表的中间节点。如果链表中的节点总数为奇数,则返回中间节点,如果链表中的节点总数为偶数,则返回中间两个节点的任意一个。可以定义两个指针,同时从链表的头节点出发,一个指针一次走一步,一个指针一次走两步。当走的快的指针走到链表的末尾时,走得慢的指针正好在链表的中间。
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead == nullptr || k == 0 ){
return nullptr;
}
ListNode *pAhead = pListHead;
ListNode *pBehind = nullptr;
for(unsigned int i =0;i<k-1;i++){
if(pAhead->next != nullptr){
pAhead = pAhead -> next;
}
else{
return nullptr;
}
}
pBehind = pListHead;
while(pAhead -> next != nullptr){
pAhead = pAhead->next;
pBehind = pBehind->next;
}
return pBehind;
}
};
还想到了一种方法:先把链表翻转,再输出第K个结点。但运行结果有问题:
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
ListNode* pNewNode = ReverseList(pListHead);
for(unsigned int i =1;i<=k+1;i++){
pNewNode = pNewNode->next;
}
return pNewNode;
}
private:
ListNode* ReverseList(ListNode* pHead){
if(pHead == nullptr || pHead->next == nullptr)
return pHead;
ListNode* pReverseNode = ReverseList(pHead->next);
pHead->next->next = pHead;
pHead->next = nullptr;
return pReverseNode;
}
};
报错error:
段错误:您的程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起
case通过率为0.00%