您的位置:首页 > Web前端

剑指Offer学习总结-链表中倒数第 k 个结点

2018-01-18 20:55 344 查看

剑指Offer学习总结-链表中倒数第 k 个结点

本系列为剑指Offer学习总结,主要是代码案例的分析和实现:

书籍链接:http://product.dangdang.com/24242724.html

原作者博客:http://zhedahht.blog.163.com/blog/static/254111742011101624433132/

原作者博客链接有完整的项目代码下载。

链表中倒数第 k 个结点

题目

题目:输入一个链表, 输出该链表中倒数第k个节点,为了符合大多数人的习惯, 本题从 1 开始计数,

即链表的尾结点是倒数第 1 个结点。 例如 一个链表有 6 个结点, 从头结点开始它们的值依次是 1、 2、 3、 4、 5、 6。

倒数第三个节点的值是4。

链表节点的定义如下:

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


常规的解法:

正常的想法,我们首先要知道链表的数据长度,需要从头遍历到尾,然后根据长度和倒数节点k的关系。

重新进行一次遍历,找个倒数第k个(整数第length +1 - k)

也是说我们通过两次遍历链表,第一次确定链表的长度,

第二次遍历找到正数的第第length +1 - k个节点,然后进行相关操作。

双指针的解法

为了实现只遍历链表一次就能找到倒数第 k 个结点, 我们可以定义两个指针。

第一个指针从链表的头指针开始遍历向前走第k-1 步,第二个指针保持不动

从第 k 步开始, 第二个指针也开始从链表的头指针开始一起移动。

由于两个指针的距离保持在 k-1的距离, 当第一个(走在前面的) 指针到达链表的尾结点时,

第二个指针( 走在后面的) 指针正好是倒数第 k 个结点。



除了基本的思路分析我们还应该考虑其他的异常情况

链表的长度本身就小于k,链表为空的情况

ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
//判断异常的参数错误
if(pListHead == NULL || k == 0)
return NULL;

ListNode *pAhead = pListHead;
ListNode *pBehind = NULL;

//循环不到k-1次  直接返回Null
for(unsigned int i = 1; i <=k - 1; ++ i)
{
if(pAhead->m_pNext != NULL)
pAhead = pAhead->m_pNext;
else
{
return NULL;
}
}

//接下来开始两个指针一起移动 直到第一个指针指向末尾节点
pBehind = pListHead;
while(pAhead->m_pNext != NULL)
{
pAhead = pAhead->m_pNext;
pBehind = pBehind->m_pNext;
}

return pBehind;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: