题目:输入一个链表,输出该链表中倒数第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%