22剑指OFFER之链表中倒数第k个节点

参考资料:

[1]剑指OFFER课本 P135

关键词:

第n-k+1个节点、先走再一起走

常规解法:

先走完一遍,再走

高级解法(背住):

倒数第1个节点,两个指针差0,先走0步,然后一起走
倒数第2个节点,两个指针差1,先走1步,然后一起走
倒数第3个节点,两个指针差2,先走2步,然后一起走

自己的解法:

改进版:

/*
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 (pListHead == nullptr)
            return nullptr;

        ListNode* pNode = pListHead;
        int nLen=0;
        //步骤1:先看链表有几个节点
        while (pNode != nullptr)
        {
            nLen++;
            pNode = pNode->next;
        }

        if (nLen < k)
            return nullptr;
        //步骤2:从头到尾找到该节点
        int nIndexForward = nLen - k;
        pNode = pListHead;
        while (nIndexForward--)
        {
            pNode = pNode->next;
        }
        return pNode;
    }

};

初始版:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
    
        //思路:
        //思路1:长度为n的链表,倒数第一个节点是n,倒数第二个节点是n-1,所以倒数第k个节点是n-k+1
        //思路2:定义两个指针,倒数第一个节点,两个指针差0,两个指针一起走。倒数第二个节点,两个指针差1,两个指针一起走
        //所以倒数第k个节点,两个指针差k-1,然后一起走.
        
        //思路1
        
        //步骤1:统计链表的长度
        ListNode* pNode = pListHead;
        int len=0;
        while(pNode!=nullptr)
        {
            pNode = pNode->next;
            len++;
        }
        //异常情况得写上
        if(pListHead == nullptr||len<k)
            return nullptr;
        
        //步骤2:输出倒数第K个节点
        //不确定,拿个实例来说话,比如1 2  倒数第1个节点,第2-1+1个节点,循环执行1次
        pNode = pListHead;//记得弄起点!!!
        for(int i=1;i<(len-k+1);i++)
        {
            pNode = pNode->next;
        }
        return pNode;
        
        /*
        //思路2:
        //步骤1:定义2个指针
        ListNode* pNode1 = pListHead;
        ListNode* pNode2 = pListHead;
        if(pNode1 == nullptr)
            return nullptr;
        
        //步骤2:倒数第1个节点。先走1步,倒数第2个节点,先走2步,倒数第k个节点,先走k步。XXXXX错误的思路
        //怎么把len给考虑进去啊
        //倒数第1个节点,两个指针差0,不用先走。倒数第2个节点,两个指针差1,1个指针先走一步。背住!!!!!!给实例验证。比如1 
        for(int i=1;i<=k-1;i++)
        {
             pNode1 = pNode1->next;
             if(pNode1 == nullptr)
                 return nullptr;
        }
        
        //步骤2:2个指针一起走
        while(pNode1->next != nullptr)
        {
            pNode1 = pNode1->next;
            pNode2 = pNode2->next;
        }
        return pNode2;
        */
    }

};
标准答案:
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
    
        //创建2个指针
        ListNode* pList1;
        ListNode* pList2;
        
        pList1 = pListHead;
        pList2 = pListHead;
        
        if(pListHead ==nullptr || k ==0)
            return nullptr;
        //k=1的时候不执行
        //2个指针,访问导数第一个指针,两个指针差0,访问倒数第2个指针,两个指针差1
        //1.
        for(int i = 1;i<=k-1;i++)
        {
            pList1 = pList1->next;
            //如果pList1指向的为空,返回
            if(pList1 == nullptr)
                return nullptr;
        }
        //2.两个指针一起访问
        while(pList1->next != nullptr)
        {
            pList1 = pList1->next;
            pList2 = pList2->next;
        }
        
        return pList2;
        
    }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容