数据结构-剑指offer-输出链表倒数第k个结点

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


猜你喜欢

转载自blog.csdn.net/baidu_32936911/article/details/80308998