剑指Offer - 面试题22:链表中倒数第K个节点

2023-11-14

题目

输入一个链表,输出该链表中倒数第K个节点。为了和服大多数人习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6.这个链表的倒数第3个节点是值为4的节点。链表节点定义如下:

分析

二次遍历

我们很容易就想到,可以先遍历一次得出链表的长度,然后再从头开始向后移动len-k个节点。
C++

#include <iostream>
using namespace std;

 /*以下为链表的实现*/
typedef int TElemType;//链表节点值的数据类型
struct ListNode
{
    TElemType Data;
    ListNode* next;
};

void CreateList(ListNode** head)
{
    ListNode* p = nullptr;
    ListNode* q = nullptr;
    int data = 1;
    (*head) = new ListNode();
    if (nullptr == head)
    {
        cout << "申请空间失败!" << endl;
        return;
    }
    
    (*head)->next = nullptr;
    (*head)->Data = data++;
    q = *head;
    while (data < 7)
    {
        p = new ListNode();
        p->Data = data++;
        p->next = nullptr;
        q->next = p;
        q = p;
    }
}

void PrintList(ListNode* head)
{
    while (head != nullptr)
    {
        cout << head->Data;
        if (head->next == nullptr)
        {
            cout << " ";
        }
        else
        {
            cout << "->";
        }
        head = head->next;
    }
    cout << endl;
}

/*查找目标节点*/
ListNode* FindKthToTail(ListNode* pListHead, int k)
{
    if (pListHead == nullptr)//传入指针为空
    {
        return nullptr;
    }
    
    int len = 0;
    ListNode* p = pListHead;
    while (p != nullptr)//遍历计算链表长度
    {
        p = p->next;
        len++;
    }
    
    if (len < k)//判断查位置是否大于链表长度
    {
        return nullptr;
    }
    int n = len - k;
    p = pListHead;//让p回到链表头部
    while (n > 0 && p != nullptr)//第二次遍历,找目标节点
    {
        p = p->next;
        n--;
    }
    return p;
}

int main()
{
    ListNode* head = nullptr;
    
    CreateList(&head);//构造链表
    PrintList(head);//输出
    ListNode* ret = FindKthToTail(head, 3);//查找

    if (ret != nullptr)
    {
        cout << "该节点为:" << ret->Data << endl;
    }
    else
    {
        cout << "传入指针为空或者查找位置大于链表长度" << endl;
    }

    return 0;
}

在这里插入图片描述

双指针+一次遍历

假设我们链表长度为6,找倒数第4个节点
在这里插入图片描述
我们可以设定快指针fast和慢指针slow让快指针先走k-1步,到节点4位置。然后快慢指针一起走,快指针走完时,慢指针刚好在节点3的位置上。实现也是比较简单的,但是不容易想到。
C++

#include <iostream>
using namespace std;

 /*以下为链表的实现*/
typedef int TElemType;//链表节点值的数据类型
struct ListNode
{
    TElemType Data;
    struct ListNode* next;
};

void CreateList(ListNode** head)
{
    ListNode* p = nullptr;
    ListNode* q = nullptr;
    int data = 1;
    (*head) = new ListNode();
    if (nullptr == head)
    {
        cout << "申请空间失败!" << endl;
        return;
    }
    
    (*head)->next = nullptr;
    (*head)->Data = data++;
    q = *head;
    while (data < 7)
    {
        p = new ListNode();
        p->Data = data++;
        p->next = nullptr;
        q->next = p;
        q = p;
    }
}

void PrintList(ListNode* head)
{
    while (head != nullptr)
    {
        cout << head->Data;
        if (head->next == nullptr)
        {
            cout << " ";
        }
        else
        {
            cout << "->";
        }
        head = head->next;
    }
    cout << endl;
}

/*查找目标节点*/
ListNode* FindKthToTail(ListNode* pListHead, int k)
{
    if (pListHead == nullptr)//传入指针为空
    {
        return nullptr;
    }

    int i = 1;
    ListNode* fast = pListHead;
    ListNode* slow = pListHead;

    //走k-1步或者链表长度小于k提前终止, 下面需要判断因为什么退出的循环
    while (i < k && fast != nullptr)
    {
        fast = fast->next;
        i++;
    }

    if (nullptr == fast)//结束循环是因为遍历到空了
    {
        return nullptr;
    }

    while (fast->next != nullptr)//快指针到头了
    {
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}

int main()
{
    ListNode* head = nullptr;
    
    CreateList(&head);//构造链表
    PrintList(head);//输出
    ListNode* ret = FindKthToTail(head, 3);//查找

    if (ret != nullptr)
    {
        cout << "该节点为:" << ret->Data << endl;
    }
    else
    {
        cout << "传入指针为空或者查找位置大于链表长度" << endl;
    }

    return 0;
}

在这里插入图片描述
本章完!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

剑指Offer - 面试题22:链表中倒数第K个节点 的相关文章

  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • 重定义;多次初始化(C++报错)

    C 中报错 b 重定义 多次初始化 如图 将a b c前面的int数据类型去掉即可
  • SpringMvc,全面讲解@RequestParam注解的用法和原理

    本文要讲的 RequestParam注解大家在开发中应该会经常的用到 但是它的某些用法我感觉你不一定都知道 所以这篇文章就讲解一下带大家拨开云雾全面了解这个注解 使大家在开发中使用到这个注解的时候不再一知半解 先看一下 RequestPar
  • 生活服务是未来十年最大的商业机会?

    编者按 本文来自有邻的投稿 内容来自有邻创始人杨仁斌周末在杭州一个 O2O 活动上的分享 文章主要是杨仁斌对于 O2O 和生活服务的一些观点分享 最后一个部分中介绍了他们自己家的 有邻 提及的数据等资料 36 氪不作背书 我的第一个观点是
  • OpenWrt系统配置UCI

    UCI简介 UCI Unified Configuration Interface 是 Openwrt 中的统一配置接口 官方文档参考 每一个程序的配置文件都保存在 etc config 目录 可以通过文本编辑器 uci 一个可执行程序 以
  • 2022年社区工作人员社区专职工作者考试精选套卷及答案

    题库来源 优题宝公众号 2022年社区工作人员社区专职工作者考试精选套卷及答案 根据最新社区工作人员社区专职工作者考试大纲与历年社区工作人员社区专职工作者考试真题汇总编写 包含社区工作人员社区专职工作者考试常考重点题型与知识点 有助于考生复
  • Metal 系列教程

    这系列文章 目前发布在我的小专栏 iOS 图像处理 上 欢迎订阅 从 2014 年 Apple 正式推出 Metal 到现在 这个 Metal 系列教程 酝酿了很久 却迟迟没有进展 直到 WWDC 2018 Apple 宣布 iOS 12
  • 社工库网址与制作方法

    将互联网泄露的信息汇聚成数据库 简单说 黑客数据库 中国执行信息公开网 http zxgk court gov cn dt dapp 1 全国标准信息公共服务平台 http std samr gov cn 征信中心 https ipcrs
  • arm启动redis报错

    报错如下 WARNING you have Transparent Huge Pages THP support enabled in your kernel This will create latency and memory usag
  • 从BOM,DOM和ECMAScript来看JavaScript

    一个老套的问题 JavaScript是由什么组成的 答 1 ECMAScript 核心 描述JS的语法和基本对象 2 文档对象模型 DOM 处理网页内容的方法和接口 3 浏览器对象模型 BOM 与浏览器交互的方法和接口 ECMAScript
  • adb logcat命令查看并过滤android输出log

    http blog csdn net hansel article details 38088583 cmd命令行中使用adb logcat命令查看Android系统和应用的log dos窗口按ctrl c中断输出log记录 logcat日
  • mysql之服务的停止和开启,登录和退出01

    1 服务的停止和开启 登录和退出 1 mysql服务的停止和开启 net stop 服务名 例如net stop MYSQL56 服务名字通过右击电脑 管理 服务和应用程序 服务获取 net start 服务名 2 MYSQL服务的登录和退
  • 抖音私信卡片私信名片的原理分析

    抖音私信卡片 解决了客户封号严重 引流效率低的痛点 所以从去年到现在 依然是热销品 抖音快手私信名片链接跳转 是2022年抖音快手引流最新技术 可以生成卡片链接 支持标题 描述 logo以及跳转落地页的完全自定义配置 支持微信公众号和微信号
  • JS对象类型的确定

    http liaofeng xiao iteye com blog 697029 JS是松散类型的语言 这一点JS的对象表现得尤为突出 那么如何来确定JS对象的具体类型呢 首先 我们可以使用typeof运算符确定其基本类型 number o
  • PHPWord 实现合并多个word文件(完结)

    PHPWord 本来想着当调包侠呢 结果翻了一遍文档 没有这种操作支持 阿这 GPT 不出意外的一顿胡扯 给 气的要中风啦 思路 word 也就是docx结尾的文件本质上就是xml字符串 两个word文件合并其实就是把两个字符串拼接起来 你
  • 一文带你理解URI 和 URL 有什么区别?

    当我们打开浏览器 要访问一个网站或者一个ftp服务器的时候 一定要输入一串字符串 比如 https blog csdn net 或者 ftp 192 168 0 111 这样我们就可以得到一个html格式的页面或者一个文件 那么这个地址是什
  • YOLO论文思路简析

    YOLO You Only Look Once Unified Real Time Object Detection 是一种2016年提出的用于视觉检测的算法 与之前的算不同 YOLO改变了检测的过程将检测转化为了一个回归问题 输出目标的b
  • Capturing iteration variables

    首先要理解Lambda表达式的延迟执行 Deferred execution An important feature of most query operators is that they execute not when constr
  • 九大遥感目标检测数据集(附下载链接)

    遥感领域目标检测数据集 码字不易 点个赞再走呗 1 UCAS AOD 3 25G 1 1基本信息 UCAS AOD Zhu et al 2015 用于飞机和汽车的检测 包含飞机与汽车2类样本以及一定数量的反例样本 背景 总共包含2420幅图
  • Linux 进程通信-共享内存Shmem示例

    linux系统共享内存是进程间共享数据最快的方法 一个进程向共享内存区域写入了数据 共享这个内存区域的所有进程就可以立刻看到其中的内容 共享内存由shmget shmat shmdt shmctl四个函数组成 具体使用说明 可以请教男人 m
  • 剑指Offer - 面试题22:链表中倒数第K个节点

    题目 输入一个链表 输出该链表中倒数第K个节点 为了和服大多数人习惯 本题从1开始计数 即链表的尾节点是倒数第1个节点 例如 一个链表有6个节点 从头节点开始 它们的值依次是1 2 3 4 5 6 这个链表的倒数第3个节点是值为4的节点 链