剑指Offer-22:链表中倒数第k个节点

题目:

输入一个链表,输出该链表中倒数第k个结点。为符合计数习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例子

如:一个链表有6个节点,从头节点开始,它们的值一次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。

链接:

剑指Offer(第2版):P134

思路标签:

  • 数据结构:链表
  • 算法:双指针
  • 代码的鲁棒性

解答:

1. C++
  • 因为是单向链表,所以无法从后向前遍历;
  • 一种直观的思路是先遍历链表得到链表的长度,然后第二次遍历就能找到第k个节点,但是需要进行两次遍历,不是好的方法;
  • 这里使用两个指针实现一次遍历,第一个指针先走k-1步,第二个指针一直不动;然后两个指针同时移动,知道第一个指针遍历完成。因为两个指针间隔为k-1,所以第二个指针指向的节点即为倒数第k个节点。
  • 需要注意代码的鲁棒性:
    • 链表为空;
    • k == 0,以为k为无符号整数,k-1=0xFFFFFFFF,导致错误;
    • 链表数不够k的情况,也就是第一个指针移动过程中变为nullptr。
/*
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 || 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;
    }
};

相关题目

求链表的中间节点,如果链表中的节点总数为奇数,则返回中间节点;如果节点总数是偶数,则返回中间两个节点的任意一个。

  • 为了解决这个问题,我们也可以定义两个指针,同时从链表的头节点出发,一个指针一次走一步,另一个指针一次走两步。
  • 当走得快的指针走到链表的末尾时,走得慢的指针正好在链表的中间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值