剑指Offer面试题:12.链表的倒数第K个结点

一题目:链表的倒数第K个结点二解题思路抛开常规解法,采用只遍历一次就能找到倒数第k个结点,可以定义两个指针:(1)第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保持不动;(2)从

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

全栈程序员社区此处内容已经被作者隐藏,请输入验证码查看内容
验证码:
请关注本站微信公众号,回复“验证码”,获取验证码。在微信里搜索“全栈程序员社区”或者“www_javaforall_cn”或者微信扫描右侧二维码都可以关注本站微信公众号。

一 题目:链表的倒数第K个结点

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

二 解题思路

  抛开常规解法,采用只遍历一次就能找到倒数第k个结点,可以定义两个指针:

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

  (2)从第k步开始,第二个指针也开始从链表的头指针开始遍历

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

三 代码实现

template <typename T>
struct Node
{
public:
    T data;
    Node *pNext;
};

template <typename T>
class ListEx
{
private:
    Node<T> *m_pHead;
    Node<T> *m_pTail;
public:
    ListEx()
    {
        m_pTail = m_pHead = NULL;
    }
    ~ListEx()
    {
        Node<T> *pTemp = NULL;
        Node<T> *pNode = m_pHead;
        while (pNode)
        {
            pTemp = pNode;
            pNode = pNode->pNext;
            delete pTemp;
        }

        m_pHead = m_pTail = NULL;
    }
    void add(T data)
    {
        Node<T> *pNode = new Node<T>;
        pNode->data = data;
        pNode->pNext = NULL;

        if (m_pHead == NULL)
        {
            m_pTail = m_pHead = pNode;
        }

        Node<T>* pTemp = m_pTail;
        pTemp->pNext = pNode;
        m_pTail = pNode;
    }

    Node<T> *GetListHead()
    {
        return m_pHead;
    }
};

// 链表的倒数第k个结点,注意倒数从1开始
template <typename T>
Node<T>* FindKthToTail(Node<T> *pNode, int k)
{
    // k必须不大于Node的结点数目
    if (!pNode || k < 0) return NULL;
    Node<T> *p1 = pNode;
    Node<T> *p2 = pNode;

    int nIndex = 0;
    bool bStart = false;
    int nFalg = 0;
    while (NULL != p2->pNext)
    {
        if (nIndex == k-1)
        {
            bStart = true;
        }
        if (bStart)
        {
            p1 = p1->pNext;
        }

        p2 = p2->pNext;
        nIndex ++;
    }
    return p1;
}

void main()
{
    ListEx<int> *pList= new ListEx<int>();
    pList->add(1);
    pList->add(2);
    pList->add(3);
    pList->add(4);
    pList->add(5);
    pList->add(6);
    pList->add(7);

    Node<int> *pHead = pList->GetListHead();
    Node<int> *pNode = FindKthToTail(pHead, 2);
    cout << pNode->data <<endl;
    pNode = FindKthToTail(pHead, 1);
    cout << pNode->data <<endl;
    pNode = FindKthToTail(pHead, 7);
    cout << pNode->data <<endl;

    delete pList;
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120162.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java静态代理_代理ip怎么设置

    Java静态代理_代理ip怎么设置Java静态代理

    2022年10月10日
    3
  • Idea激活码最新教程2024.3.4.1版本,永久有效激活码,亲测可用,记得收藏

    Idea激活码最新教程2024.3.4.1版本,永久有效激活码,亲测可用,记得收藏Idea 激活码教程永久有效 2024 3 4 1 激活码教程 Windows 版永久激活 持续更新 Idea 激活码 2024 3 4 1 成功激活

    2025年5月31日
    9
  • Vue 插槽之 作用域插槽「建议收藏」

    现在我有如下需求,子组件<user/>中此时有一条用户的信息(userInfo);我要在父组件通过插槽展示这个用户的姓名(userInfo.name);注意:这里的父组件并没有这个用户的信息,子组件中有,如果直接在父组件{{userInfo.name}}获取这条信息是获取不到的;因为,只有<user/>组件可以访问到userInfo,而我们提供的内容是在父…

    2022年4月13日
    65
  • Java中的BufferedReader与BufferedWriter简介与使用

    Java中的BufferedReader与BufferedWriter简介与使用BufferedReader和BufferedWriter是带有默认缓冲区的字符输入输出流,其效率相较于没有缓冲区要高:   1.java.io.BufferedReader和java.io.BufferedWriter类各拥有8192字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。…

    2022年5月4日
    46
  • char* 和char[]的差别

    char* 和char[]的差别

    2021年11月14日
    45
  • [数据仓库]分层概念,ODS,DM,DWD,DWS,DIM的概念「建议收藏」

    [数据仓库]分层概念,ODS,DM,DWD,DWS,DIM的概念「建议收藏」ODS是什么?ODS全称是OperationalDataStore,操作数据存储.“面向主题的”,数据运营层,也叫ODS层,是最接近数据源中数据的一层,数据源中的数据,经过抽取、洗净、传输,也就说传说中的ETL之后,装入本层。本层的数据,总体上大多是按照源头业务系统的分类方式而分类的。但是,这一层面的数据却不等同于原始数据。在源数据装入这一层时,要进行诸如去噪(例如有一条数据中人的年龄是300岁,这种属于异常数据,就需要提前做一些处理)、去重(例如在个人资料表中,同一ID却有两条重复

    2022年4月19日
    110

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号