剑指Offer第15题(链表中倒数第k个结点)

(本博客旨在个人总结回顾)

题目描述:

       输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。

链表结点定义如下:

struct ListNode
{
    int            m_nValue;
    ListNode*      m_pNext;  
};

解题思路:

使用两个指针A,B,将B指针移动到第K个结点,然后将A设置为头结点,将两结点同时一步一步往下一结点移动,当B结点移动到尾结点时,A结点就刚好移动到倒数第K个结点。

考虑输入的异常情况:①链表结点数少于k的情况;②k<=0的情况。③链表为NULL

目标函数:

/*
 * @name   GetKthToTail
 * @brief  获取链表的倒数第k个结点
 * @param  [in] ListNode * pListHead
 * @param  [in] int k
 * @return ListNode*
 */
 ListNode* GetKthToTail(ListNode* pListHead, int k)
{
    if (NULL == pListHead || k <= 0)
    {
        return NULL;
    }

    ListNode* pAHead = pListHead;
    ListNode* pFind = pListHead;

    //pAHead设置为第K个结点(从1开始计算)
    for (int i = 1; i < k ; i++)
    {
        if (pAHead->m_pNext != NULL)
        {
            pAHead = pAHead->m_pNext;
        }
        else
        {
            return NULL;
        }
    }

    //pAHead移动的最后一个结点
    //pFind刚好就移动至第K个结点
    while (pAHead->m_pNext != NULL)
    {
        pAHead = pAHead->m_pNext;
        pFind = pFind->m_pNext;
    }
    return pFind;
}

完整测试代码:


#include "stdafx.h"
#include <iostream>
using namespace std;

struct ListNode
{
    int         m_nValue;
    ListNode*   m_pNext;
};


/*
 * @name   GetKthToTail
 * @brief  获取链表的倒数第k个结点
 * @param  [in] ListNode * pListHead
 * @param  [in] int k
 * @return ListNode*
 */
 ListNode* GetKthToTail(ListNode* pListHead, int k)
{
    if (NULL == pListHead || k <= 0)
    {
        return NULL;
    }

    ListNode* pAHead = pListHead;
    ListNode* pFind = pListHead;

    //pAHead设置为第K个结点(从1开始计算)
    for (int i = 1; i < k ; i++)
    {
        if (pAHead->m_pNext != NULL)
        {
            pAHead = pAHead->m_pNext;
        }
        else
        {
            return NULL;
        }
    }

    //pAHead移动的最后一个结点
    //pFind刚好就移动至第K个结点
    while (pAHead->m_pNext != NULL)
    {
        pAHead = pAHead->m_pNext;
        pFind = pFind->m_pNext;
    }
    return pFind;
}


int _tmain(int argc, _TCHAR* argv[])
{
    //测试1题描述例子
    ListNode* pHead1 = new ListNode();
    pHead1->m_nValue = 1;
    ListNode* pTmp = new ListNode();
    pTmp->m_nValue = 2;
    pHead1->m_pNext = pTmp;

    pTmp->m_pNext = new ListNode();
    pTmp = pTmp->m_pNext;
    pTmp->m_nValue = 3;

    pTmp->m_pNext = new ListNode();
    pTmp = pTmp->m_pNext;
    pTmp->m_nValue = 4;

    pTmp->m_pNext = new ListNode();
    pTmp = pTmp->m_pNext;
    pTmp->m_nValue = 5;

    pTmp->m_pNext = new ListNode();
    pTmp = pTmp->m_pNext;
    pTmp->m_nValue = 6;

    ListNode* pKNode = GetKthToTail(pHead1, 3);
    if (pKNode != NULL)
    {
        cout << "测试例子1:倒数第3个结点值为" << pKNode->m_nValue << endl;
    }    
    else
    {
        cout << "测试例子1:不存在该结点" << endl;
    }

    //测试2链表结点数小于K
    pKNode = GetKthToTail(pHead1, 7);
    if (pKNode != NULL)
    {
        cout << "测试例子2:倒数第7个结点值为" << pKNode->m_nValue << endl;
    }
    else
    {
        cout << "测试例子2:不存在该结点" << endl;
    }

    //测试3链表结点数等于1,k=1
    pKNode = GetKthToTail(pTmp, 1);
    if (pKNode != NULL)
    {
        cout << "测试例子3:倒数第1个结点值为" << pKNode->m_nValue << endl;
    }
    else
    {
        cout << "测试例子3:不存在该结点" << endl;
    }

    //测试4:K <= 0
    pKNode = GetKthToTail(pTmp, 0);
    if (NULL == pKNode)
    {
        cout << "测试例子4:不存在该结点" << endl;
    }
    pKNode = GetKthToTail(pTmp, -1);
    if (NULL == pKNode)
    {
        cout << "测试例子4:不存在该结点" << endl;
    }

    //测试5:链表NULL
    pKNode = GetKthToTail(NULL, 1);
    if (NULL == pKNode)
    {
        cout << "测试例子5:不存在该结点" << endl;
    }

    system("pause");
    return 0;
}

运行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值