剑指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个节点 的相关文章

  • 尚未注册类型“IServiceProviderFactory[Autofac.ContainerBuilder]”的服务

    当运行以下命令添加数据库迁移脚本时 出现以下错误 dotnet ef migrations add InitialCreate v o Migrations context MyContext 访问 Microsoft Extensions
  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • 我如何理解这个 C 类型声明?

    double bar int double double double double 在查看讲座幻灯片时 我发现了留给学生的练习 用简单的英语来说 什么是类型bar在这个 C 声明中 Please帮助我解决这个问题 我什至不知道从哪里开始
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • 在 Xamarin 中隐藏软键盘

    如何隐藏软键盘以便在聚焦时显示Entry在 Xamarin forms 便携式表单项目中 我假设我们必须为此编写特定于平台的渲染器 但以下内容不起作用 我创建自己的条目子类 public class MyExtendedEntry Entr
  • 根据 N 个值中最小的一个返回不同的结果

    不确定如何使标题更具描述性 所以我只是从一个例子开始 我使用下面的代码位 它从枚举中选择一个方向 具体取决于四个轴中哪一个与给定方向相比形成最小角度 static Direction VectorToDirection Vector2 di
  • 如何在 SqlDataReader.Read() 期间从死锁异常中恢复

    我的 NET 应用程序的事件日志显示 它在从 Sql Server 读取数据时偶尔会出现死锁 这种情况通常非常罕见 因为我们已经优化了查询以避免死锁 但有时仍然会发生 过去 我们在调用ExecuteReader函数在我们的SqlComman
  • ASP.Net Core 内容配置附件/内联

    我正在从 WebAPI 控制器返回一个文件 Content Disposition 标头值自动设置为 附件 例如 处置 附件 文件名 30956 pdf 文件名 UTF 8 30956 pdf 当它设置为附件时 浏览器将要求保存文件而不是打
  • 时间:2019-03-17 标签:c#ThreadSafeDeepCopy

    我一直在阅读很多其他问题以及大量谷歌搜索 但我一直无法找到明确的解决方案 根据我读过的一些最佳实践 类的静态方法应该创建线程安全的 并且实例成员应该将线程安全留给消费者 我想为该类实现深度复制方法 该类本身还有其他引用类型成员 有没有什么方
  • fprintf() 线程安全吗?

    我正在为野人就餐问题的某些变量编写一个 C 解决方案 现在 我创建线程 每个线程都将 FILE 获取到同一个调试文件 在线程内我正在使用 fprintf 进行一些打印 打印的语句不受任何类型的互斥锁等保护 我没有在调试文件中观察到任何交错行
  • 类的成员复制

    在学习 复制成员 概念时 书中给出了如下说法 此外 如果非静态成员是引用 const 或没有复制赋值的用户定义类型 则无法生成默认赋值 我不太明白这个声明到底想传达什么 或者说这个说法指的是哪一种场景 谢谢 该语句与编译器自动为您编写的类
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 给出 5 个参数,但在终端中只得到 3 个参数

    我想将一个文件传递给一个c 程序 如果我在 IDE 中执行此操作 test string string lt test txt return argc 5 但在终端上我刚刚得到argc 3 看来 这是因为 什么是 lt 意思是 我正在使用
  • 如何在标准 WPF ListView 中启用 UI 虚拟化

    我正在使用 NET 4 5 VS2012 并且我有一个 ListView 看起来像这样
  • 将标量添加到特征矩阵(向量)

    我刚刚开始使用 Eigen 库 无法理解如何向所有矩阵成员添加标量值 假设我有一个矩阵 Eigen Matrix3Xf mtx Eigen Matrix3Xf Ones 3 4 mtx mtx 1 main cxx 104 13 error
  • ASP.NET MailMessage.BodyEncoding 和 MailMessage.SubjectEncoding 默认值

    很简单的问题 但我在 MSDN 上找不到答案 查找 ASP NET 将用于的默认值 MailMessage BodyEncoding and MailMessage SubjectEncoding 如果你不在代码中设置它们 Thanks F
  • 使用restsharp序列化对象并将其传递给WebApi而不是序列化列表

    我有一个看起来像的视图模型 public class StoreItemViewModel public Guid ItemId get set public List
  • 每个数据库多个/单个 *.edmx 文件

    我有一个通过 ADO net 数据服务与数据库交互的项目 数据库很大 近 150 个具有依赖关系的表 该项目几年前开始 当时使用的是数据集 现在我们正在转向实体模型关系 由于我们添加了更多需要使用的表 该模型正在不断增长 这是管理这一切的正
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959

随机推荐

  • 重定义;多次初始化(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的节点 链