可视化图解算法:链表中倒数(最后)k个结点

1. 题目

描述

输入一个长度为 n 的链表,设链表中的元素的值为ai ,返回该链表中倒数第k个节点。

如果该链表长度小于k,请返回一个长度为 0 的链表。

数据范围:0≤n≤105,0 ≤ai≤109,0 ≤k≤109

要求:空间复杂度 O(n),时间复杂度 O(n)

进阶:空间复杂度 O(1),时间复杂度 O(n)

例如输入{1,2,3,4,5},2时,对应的链表结构如下图所示:

其中蓝色部分为该链表的最后2个结点,所以返回倒数第2个结点(也即结点值为4的结点)即可,系统会打印后面所有的节点来比较。

示例1

输入:

{1,2,3,4,5},2

返回值:

{4,5}

说明:

返回倒数第2个节点4,系统会打印后面所有的节点来比较。 

示例2

输入:

{2},8

返回值:

{}

2. 解题思路

获取链表的倒数第K个节点,最先想到的是先获取链表的长度n(共多少个节点,时间复杂度为n),之后再从前向后查找,遍历n-k个节点。

此题还有一种巧妙的解法:双指针法。通过此方法可以遍历一次查找到对应的节点。

假如链表结构如下图所示,给定k=2,即查找倒数第2个节点(值为4的节点):

这时,可以通过以下步骤完成:

第一步:定义快慢指针。

第二步:移动快指针 k 次(每次移动1个节点)。

k=2,即快指针先移动k次(每次一个节点),这时fast会指向3节点。

第三步:快慢指针一起移动(每次移动1个节点),一直到快指针fast指向Null停下来。

第四步:快指针指向为None,慢指针指向的节点为:倒数第k个节点。

如果文字描述的不太清楚,你可以参考视频的详细讲解。

  • Python版本:哔哩哔哩_bilibilihttps://www.bilibili.com/cheese/play/ep1370264

  • Java版本:数据结构笔试面试算法-Java语言版_哔哩哔哩_bilibili数据结构笔试面试算法-Java语言版,bilibili课堂,哔哩哔哩课堂,哔哩哔哩,Bilibili,B站,弹幕https://www.bilibili.com/cheese/play/ep1366720

  • Golang版本:哔哩哔哩_bilibilihttps://www.bilibili.com/cheese/play/ep1364397

3. 编码实现

3.1 Python编码实现

class ListNode:def __init__(self, x):self.val = x  # 链表的数值域self.next = None  # 链表的指针域# 从链表节点尾部添加节点
def insert_node(node, value):if node is None:print("node is None")return# 创建一个新节点new_node = ListNode(value)cur = node# 找到链表的末尾节点while cur.next is not None:cur = cur.next# 末尾节点的next指针域连接新节点cur.next = new_node# 打印链表(从链表头结点开始打印链表的值)
def print_node(node):cur = node# 遍历每一个节点while cur is not None:print(cur.val, end="\t")cur = cur.next  # 更改指针变量的指向print()#
#
# @param pHead ListNode类
# @param k int整型
# @return ListNode类
#
class Solution:def FindKthToTail(self, pHead: ListNode, k: int) -> ListNode:# write code here# 1.  定义快慢指针fast = pHeadslow = pHead# 2. 移动快指针  k 次(每次移动1个节点)for i in range(k):if fast is None:return None  # k大于链表长度的情况fast = fast.next# 3. 快慢指针一起移动(每次移动1个节点)while fast is not None:fast = fast.nextslow = slow.next# 4. 快指针指向为None,慢指针指向的节点为:到时候第k个节点return slowif __name__ == '__main__':head = ListNode(1)insert_node(head, 2)insert_node(head, 3)insert_node(head, 4)insert_node(head, 5)print_node(head)s = Solution()node = s.FindKthToTail(head, 2)print(node.val)print_node(node)

3.2 Java编码实现

package LL08;public class Main {//定义链表节点static class ListNode {private int val;  //链表的数值域private ListNode next; //链表的指针域public ListNode(int data) {this.val = data;this.next = null;}}//添加链表节点private static void insertNode(ListNode node, int data) {if (node == null) {return;}//创建一个新节点ListNode newNode = new ListNode(data);ListNode cur = node;//找到链表的末尾节点while (cur.next != null) {cur = cur.next;}//末尾节点的next指针域连接新节点cur.next = newNode;}//打印链表(从头节点开始打印链表的每一个节点)private static void printNode(ListNode node) {ListNode cur = node;//遍历每一个节点while (cur != null) {System.out.print(cur.val + "\t");cur = cur.next; //更改指针变量的指向}System.out.println();}public static class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** @param pHead ListNode类* @param k     int整型* @return ListNode类*/public ListNode FindKthToTail(ListNode pHead, int k) {// write code here// 1. 定义快慢指针ListNode fast = pHead;ListNode slow = pHead;// 2. 移动快指针 k 次(每次移动1个节点)for (int i = 0; i < k; i++) {if (fast == null) {return null; //k大于链表长度的情况}fast = fast.next;}// 3. 快慢指针一起移动(每次移动1个节点)while (fast != null) {fast = fast.next;slow = slow.next;}// 4. 快指针指向为null,慢指针指向的节点为:到时候第k个节点return slow;}}public static void main(String[] args) {ListNode head = new ListNode(1);insertNode(head, 2);insertNode(head, 3);insertNode(head, 4);insertNode(head, 5);printNode(head);Solution solution = new Solution();ListNode node = solution.FindKthToTail(head, 2);System.out.println(node.val);printNode(node);}
}

3.3 Golang编码实现

package mainimport "fmt"// ListNode 定义链表节点
type ListNode struct {Val  int       //链表的数值域Next *ListNode //链表的指针域
}/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param pHead ListNode类* @param k int整型* @return ListNode类*/
func FindKthToTail(pHead *ListNode, k int) *ListNode {// write code here// 1. 定义快慢指针fast := pHeadslow := pHead// 2. 移动快指针 k 次(每次移动1个节点)for i := 0; i < k; i++ {if fast == nil {return nil //k大于链表长度的情况}fast = fast.Next}// 3. 快慢指针一起移动(每次移动1个节点)for fast != nil {fast = fast.Nextslow = slow.Next}// 4. 快指针指向为nil,慢指针指向的节点为:到时候第k个节点return slow
}
func main() {head := ListNode{Val: 1}head.Insert(2)head.Insert(3)head.Insert(4)head.Insert(5)head.Print()node := FindKthToTail(&head, 2)fmt.Println(node.Val)node.Print()
}// Insert 从链表节点尾部添加节点
func (ln *ListNode) Insert(val int) {if ln == nil {return}//创建一个新节点newNode := &ListNode{Val: val}cur := ln//找到链表的末尾节点for cur.Next != nil {cur = cur.Next}//末尾节点的next指针域连接新节点cur.Next = newNode
}// Print 从链表头结点开始打印链表的值
func (ln *ListNode) Print() {if ln == nil {return}cur := ln//遍历每一个节点for cur != nil {fmt.Print(cur.Val, "\t")cur = cur.Next //更改指针变量的指向}fmt.Println()
}

如果上面的代码理解的不是很清楚,你可以参考视频的详细讲解。

  • Python版本:哔哩哔哩_bilibili

  • Java版本:数据结构笔试面试算法-Java语言版_哔哩哔哩_bilibili

  • Golang版本:哔哩哔哩_bilibilihttps://www.bilibili.com/cheese/play/ep1364397

4.小结

获取链表的倒数(最后)第k个节点,可以通过快慢指针快速获取到:

  • 定义快慢指针。

  • 移动快指针 k 次(每次移动1个节点)。

  • 快慢指针一起移动(每次移动1个节点),一直到快指针fast指向Null停下来。

  • 快指针指向为None,慢指针指向的节点为:倒数第k个节点。

更多算法视频讲解,你可以从以下地址找到:

  • Python编码实现:数据结构笔试面试算法-Python语言版_哔哩哔哩_bilibili数据结构笔试面试算法-Python语言版,bilibili课堂,哔哩哔哩课堂,哔哩哔哩,Bilibili,B站,弹幕https://www.bilibili.com/cheese/play/ep1509965

  • Java编码实现:哔哩哔哩_bilibilihttps://www.bilibili.com/cheese/play/ep1510007

  • Golang编码实现:数据结构笔试面试算法-Go语言版_哔哩哔哩_bilibili数据结构笔试面试算法-Go语言版,bilibili课堂,哔哩哔哩课堂,哔哩哔哩,Bilibili,B站,弹幕https://www.bilibili.com/cheese/play/ep1509945

对于链表的相关操作,我们总结了一套【可视化+图解】方法,依据此方法来解决链表相关问题,链表操作变得易于理解,写出来的代码可读性高也不容易出错。具体也可以参考视频详细讲解。

今日佳句:问渠那得清如许?为有源头活水来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/36627.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Quartz知识点总结

简单说明 简单的定时任务使用Timer或者ScheduledExecutorService quartz支持复杂的定时执行功能。支持ram存储&#xff08;内存存储&#xff09;和持久化存储。quartz有分布式和集群能力 简单使用 获取任务调度器Schedule。任务调度器可以管理任务。创建任务实例。使用JobB…

C语言每日一练——day_12(最后一天)

引言 针对初学者&#xff0c;每日练习几个题&#xff0c;快速上手C语言。第十二天。&#xff08;最后一天&#xff0c;完结散花啦&#xff09; 采用在线OJ的形式 什么是在线OJ&#xff1f; 在线判题系统&#xff08;英语&#xff1a;Online Judge&#xff0c;缩写OJ&#xff0…

【宇宙回响】从Canvas到MySQL:飞机大战的全栈交响曲【附演示视频与源码】

&#x1f31f; 这是星际大战系列的第三篇送福利文章&#xff0c;感谢一路以来支持和关注这个项目的每一位朋友&#xff01; &#x1f4a1; 文章力求严谨&#xff0c;但难免有疏漏之处&#xff0c;欢迎各位朋友指出&#xff0c;让我们一起在交流中进步。 &#x1f381; 项目代码…

数据结构知识点1

目录 一、时间复杂度和空间复杂度 1.1时间复杂度&#xff1a; 1.2空间复杂度&#xff1a; 二、装箱和拆箱 三、泛型 3.1泛型类的使用&#xff1a; 3.2泛型的上界&#xff1a; 3.3泛型方法&#xff1a; 一、时间复杂度和空间复杂度 1.1时间复杂度&#xff1a; 时间复杂…

华为ipd流程华为流程体系管理华为数字化转型流程数字化管理解决方案介绍81页精品PPT

华为流程体系最佳实践主要包括构建完善的流程框架&#xff0c;明确各层级流程要素与职责&#xff0c;梳理涵盖研发、采购、营销、服务、资产管理等多领域的流程&#xff0c;通过梳理业务场景和核心能力搭建差异化流程框架&#xff0c;采用自上而下与自下而上相结合的建模方法&a…

在大数据开发中ETL是指什么?

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在数字经济时代&#xff0c;数据已成为企业最核心的资产。然而&#xff0c;分散在业务系统、日志文件…

Collection系列集合的小结+集合并发修改异常问题

一、Collection系列集合的小结 二、补充知识&#xff1a;集合的并发修改异常问题 三、Collection的其他相关知识 1. 前置知识&#xff1a;可变参数 2. 集合的工具类&#xff1a;Collections 3. 综合案例&#xff1a;斗地主游戏 &#xff08;1&#xff09;创建Card类 public c…

QT Quick(C++)跨平台应用程序项目实战教程 2 — 环境搭建和项目创建

目录 引言 1. 安装Qt开发环境 1.1 下载Qt安装包 1.2 安装Qt 1.3 安装Visual Studio 2022 1.4 在Visual Studio 2022中安装Qt插件 1.5 在Visual Studio 2022中安装大模型编程助手 2. 创建Qt Quick项目 2.1 创建新项目 2.2 项目结构 2.3 运行项目 3. 理解项目代码 3…

免密登录远程服务器shell脚本

一、脚本代码 #!/bin/bash #提示用户输入用户i名和ip地址 read -p "请输入远程服务器的用户名: " hname read -p "请输入远程服务器的IP地址: " fip read -p "请输入远程服务器的远程端口:" sdk #检查是否配置了免密登录 function sfmm(){ …

repo init 错误 Permission denied (publickey)

一、已经生成ssh-key并设置到gerrit上 二、已经设置.gitconfig &#xff08;此步骤是公司要求&#xff0c;设置gerrit地址为一个别名之类的&#xff0c;有的公司不需要&#xff09; 然后出现下面的错误&#xff0c;最后发现忘记设置git的用户名和邮箱 1. git config --globa…

卷积神经网络 - 汇聚层

卷积神经网络一般由卷积层、汇聚层和全连接层构成&#xff0c;本文我们来学习汇聚层。 汇聚层(Pooling Layer)也叫子采样层(Subsampling Layer)&#xff0c;其作用是进 行特征选择&#xff0c;降低特征数量&#xff0c;从而减少参数数量。 卷积层虽然可以显著减少网络中连接的…

C++ 头文件说明

如果一个程序足够大&#xff0c;代码功能很多&#xff0c;可以想象&#xff0c;不可能把代码写在一个cpp文件里。我们需要模块化&#xff0c;这样的好处很多&#xff0c;方便分工合作&#xff0c;可读性提高&#xff0c;调用也方便。 这个要怎么做呢&#xff1f; 很简单直接当…

【蓝桥杯】省赛:分糖果(思维/模拟)

思路 数据很小&#xff0c;直接暴力模拟。 有意思的是一个列表如何当成循环队列写&#xff1f;可以arr[(i1)%n]让他右边超出时自动回到开头。 code import os import sysn int(input()) arr list(map(int,input().split()))ans 0 while 1:arr1 arr.copy()for i in range…

如何理解分布式光纤传感器?

关键词&#xff1a;OFDR、分布式光纤传感、光纤传感器 分布式光纤传感器是近年来备受关注的前沿技术&#xff0c;其核心在于将光纤本身作为传感介质和信号传输介质&#xff0c;通过解析光信号在光纤中的散射效应&#xff0c;实现对温度、应变、振动等物理量的连续、无盲区、高…

【java面型对象进阶】------继承实例

继承结构下的标准Javabean 代码如下&#xff1a; package demo10;//定义员工父类 public class Employee {private String id;private String name;private double salary;//构造方法public Employee(){}public Employee(String id,String name,double salary){this.idid;thi…

matrix-breakout-2-morpheus 靶机----练习攻略 【仅获取shell】

【此练习仅做到反弹shell】 1.靶机下载地址 https://download.vulnhub.com/matrix-breakout/matrix-breakout-2-morpheus.ova 2. 打开靶机&#xff0c;kali使用nmap扫描同C段的主机 找到靶机ip 确保靶机和kali网卡均为NAT模式 先查看kali的ip nmap 192.168.182.1/24 …

解锁MySQL 8.0.41源码调试:Mac 11.6+CLion 2024.3.4实战指南

文章目录 解锁MySQL 8.0.41源码调试&#xff1a;Mac 11.6CLion 2024.3.4实战指南前期准备环境搭建详细步骤安装 CLion安装 CMake 3.30.5准备 MySQL 8.0.41 源码配置 CMake 选项构建 MySQL 项目 调试环境配置与验证配置 LLDB 调试器启动调试验证调试环境 总结与拓展碰到的问题1.…

使用码云搭建CocoaPods远程私有库

一、创建远程私有索引库 用来存放私有框架的详细描述信息.podspec文件 1. 创建私有库 假设码云上创建的私有库为repo-spec 2. 查看本地已存在的索引库 pod repo list 3. 将远程私有索引库添加到本地 pod repo add [https://gitee.com/jingluoguo/repo-spec.git](https://gi…

Devops之AWS:如何安装AWS CLI

AWS 命令行界面&#xff08;AWS CLI&#xff09;是一种开源工具&#xff0c;让我们能够使用命令行 Shell 中的命令与 AWS 服务进行交互。 安装步骤&#xff1a; 下载并运行AWS CLI的MSI安装程序&#xff1a; 点击如下的链接&#xff0c;即可下载MSI安装程序&#xff1a; htt…

docker需要sudo才能使用

一种方法是添加当前用户到docker组里去&#xff0c;当时添加的时候貌似是没问题的&#xff0c;但是现在又不可以了 产生的报错 ❯ docker images Cannot connect to the Docker daemon at unix:///home/ying/.docker/desktop/docker.sock. Is the docker daemon running?解决…