剑指offer面试题[15]-链表中倒数第K个结点

来源:互联网 发布:dp901单片机说明书 编辑:程序博客网 时间:2024/06/14 08:10

题目描述

输入一个链表,输出该链表中倒数第k个结点。

思路:

         假设链表有n个结点,那么倒数第k个结点就是从头结点开始的第n-k+1个结点,我们只要从头结点开始往后走n-k+1步就可以了。那么问题来了:如何计算n?这个其实也不难,从头开始遍历链表,每经过一个结点,计数器加1就行了。

         也就是说我们需要遍历链表两次,第一次统计出链表中结点的个数,第二次就能找到倒数第k个结点。但是如果面试官要求只能遍历一次链表呢?

         为了实现只遍历链表一次就能找到倒数第k个结点,我们可以定义两个指针。第一个指针从头结点开始遍历向前走k-1步,第二个指针不动;从第k步开始,第二个指针也开始从链表的头结点开始遍历。由于两个指针的距离始终是k-1,因此当第一个指针到达链表的尾结点时,第二个指针正好是倒数第k个结点。

        需要注意的是代码的鲁棒性:判断k是否为0及链表是否为空的情况,还有链表的长度是否小于k。

        最好的理解方式就是自己举个例子分析下。

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
    if(pListHead==NULL||k==0)
        return NULL;
    ListNode* p1=pListHead;
    ListNode* p2=NULL;
    for(int i=0;i<k-1;i++)
       {
         if(p1->next==NULL)      //这里就是为了判断链表的长度是否小于k,因为如果链表的长度小于k,还未等到i执行到i=k-2时,p1->next就会为空
             return NULL;
         p1=p1->next;
       } 
    p2=pListHead;
    for(ListNode*p=p1;p->next!=NULL;p=p->next)              //一定注意这里的p->next!=NULL
        {
            p2=p2->next;
        }
    return p2;
    }
};

阅读全文
1 0