Python面试宝典第4题:环形链表

题目

        给你一个链表的头节点 head ,判断链表中是否有环。如果存在环 ,则返回 true 。 否则,返回 false 。

        如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

        示例:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

快慢指针法

        快慢指针法,也叫Floyd判圈法,是解决链表中环检测问题的经典算法。其核心思想是使用两个指针,一个快指针每次移动两个节点,一个慢指针每次移动一个节点。如果链表中存在环,快慢指针最终会在环中的某一点相遇。若不存在环,快指针会先到达链表尾部。使用快慢指针法求解本题的主要步骤如下。

        1、初始化指针。开始时,定义两个指针,一个快指针(fast)和一个慢指针(slow),均指向链表的头节点。

        2、移动指针。每次迭代时,慢指针(slow)向前移动一步,快指针(fast)向前移动两步。如果链表中存在环,由于快指针移动速度是慢指针的两倍,最终快指针会追上慢指针。

        3、终止条件。如果链表中没有环,快指针会首先到达链表的尾部(None),这时可以确定链表无环。相反,如果快慢指针相遇,则表明链表中存在环。

        根据上面的算法步骤,我们可以得出下面的示例代码。

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

def create_linked_list(length, pos = -1):
    if length < 1 or (pos != -1 and (pos < 0 or pos >= length)):
        return None
    
    head = ListNode(0)
    current = head
    cycle_node = None
    
    for i in range(1, length + 1):
        new_node = ListNode(i)
        current.next = new_node
        current = new_node
        if i == pos + 1:
            cycle_node = new_node
    
    # 只有当pos有效且不为-1时,才创建环
    if cycle_node:
        current.next = cycle_node
    
    # 返回真正的头节点,忽略初始的0节点
    return head.next

def has_cycle_fast_slow_pointer(head):
    if head is None or head.next is None:
        return False
    
    slow = head
    fast = head.next
    
    while fast is not None and fast.next is not None:
        if slow == fast:
            return True
        slow = slow.next
        fast = fast.next.next
    
    return False

# 创建有环链表
head_with_cycle = create_linked_list(4, 1)
# 输出: True
print(has_cycle_fast_slow_pointer(head_with_cycle))

# 创建无环链表
head_no_cycle = create_linked_list(4, -1)
# 输出: False
print(has_cycle_fast_slow_pointer(head_no_cycle))

哈希表法

        哈希表法利用数据结构中的哈希表来记录每个访问过的节点。由于哈希表的查找效率非常高,平均时间复杂度为O(1),故我们可以在遍历链表的同时,将每个访问过的节点添加到哈希表中。当发现某个节点已经被访问过,即该节点存在于哈希表中时,则可断定链表中存在环。使用哈希表法求解本题的主要步骤如下。

        1、初始化。创建一个空的哈希表,在Python中,通常是集合set。

        2、遍历链表。从链表头开始遍历,对于每一个访问到的节点,执行以下操作。

        (1)检查当前节点是否已经在哈希表中。

        (2)如果不在,将当前节点添加到哈希表中,并继续遍历下一个节点。

        (3)如果在哈希表中发现了当前节点,说明存在环,直接返回True。

        3、遍历结束。如果遍历完整个链表都没有发现重复的节点,则说明链表中没有环,返回False。

        根据上面的算法步骤,我们可以得出下面的示例代码。

def has_cycle_hashset(head):
    visited_nodes = set()
    while head is not None:
        # 如果节点已经在集合中,说明有环
        if head in visited_nodes:
            return True
        visited_nodes.add(head)
        head = head.next
    
    # 遍历结束,没有发现环
    return False

# 创建有环链表
head_with_cycle = create_linked_list(4, 1)
# 输出: True
print(has_cycle_hashset(head_with_cycle))

# 创建无环链表
head_no_cycle = create_linked_list(4, -1)
# 输出: False
print(has_cycle_hashset(head_no_cycle))

总结

        快慢指针法不需要额外的空间,时间复杂度为O(n),其中n是链表中的节点数量。哈希表法则提供了另一种思路,虽然它需要额外的O(n)空间,但优点是实现直观,易于理解和编码。

        在实际应用中,如果对空间复杂度有严格要求,推荐使用快慢指针法。如果空间不是问题,而对代码的简洁性和直观性有更高要求,哈希表法也是一个不错的选择。

💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号“希望睿智”。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《涅朵奇卡:一个女人的一生》读后感

这周的计划是看完海明威的《丧钟为谁而鸣》&#xff0c;但是因为下班晚&#xff0c;而且书的体量大&#xff0c;所以只看了一半。本来以为这周的阅读计划完不成了&#xff0c;不料昨天加完班后拿起新到的《涅朵奇卡&#xff1a;一个女人的一生》&#xff0c;不自觉就陷进去了&a…

Cocos如何跟Android通信?

点击上方亿元程序员+关注和★星标 引言 Cocos如何跟Android通信 大家好,相信小伙伴们通过阅读笔者前几期的文章**《Cocos打安卓包打不出来?看看这个》,对Cocos**如何打安卓包有了一定的了解。 但是,除了把安卓包打出来,另外还有一个重要的就是要能够调用安卓提供的Java方…

时钟切换的代码

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 参考代码 描述 题目描述&#xff1a; 存在两个同步的倍频时钟clk0 clk1,已知clk0是clk1的二倍频&#xff0c;现在要设计一个切换电路&#xff0c;sel选择时候进行切换&#xff0c;要求没有毛刺。 信号示意图&…

Web 基础与 HTTP 协议

Web 基础与 HTTP 协议 一、Web 基础1.1域名和 DNS域名的概念Hosts 文件DNS&#xff08;Domain Name System 域名系统&#xff09;域名注册 1.2网页与 HTML网页概述HTML 概述网站和主页Web1.0 与 Web2.0 1.3静态网页与动态网页静态网页动态网页 二、HTTP 协议1.1HTTP 协议概述1.…

学习springAOP

第三章 Spring AOP 第一节 AOP 简介 1. 概念 AOP全称为Aspect Oriented Programming&#xff0c;表示面向切面编程。何为切面呢&#xff1f; 由此可以得出&#xff0c;切面是一种将那些与业务无关&#xff0c;但业务模块都需要使用的功能封装起来的技术。这样便于减少系统的…

three.js地理坐标系有哪些,和屏幕坐标系的转换。

坐标系很好理解&#xff0c;就是点线面体的位置&#xff0c;一个点是一个坐标&#xff0c;一条线段2个坐标&#xff0c;一个矩形四个坐标&#xff0c;一个立方体8个坐标&#xff0c;three.js面对的是三维空间&#xff0c;屏幕则是二维的&#xff0c;这就面临着转换问题&#xf…

【Python机器学习系列】建立决策树模型预测小麦品种(案例+源码)

这是我的第314篇原创文章。 一、引言 对于表格数据&#xff0c;一套完整的机器学习建模流程如下&#xff1a; 针对不同的数据集&#xff0c;有些步骤不适用&#xff0c;其中橘红色框为必要步骤&#xff0c;欢迎大家关注翻看我之前的一些相关文章。前面我介绍了机器学习模型的二…

grpc编译 helloworld

【1】打开helloworld所在目录 examples\cpp\helloworld 【2】CMAKE生成会报错 【3】问题解决&#xff1a;增加环境变量path “C:\Program Files (x86)\grpc\bin” 是上一篇grpc编译后安装的目录 【4】CMAKE后直接用“Open Project”打开项目

Java关于标准输入和标准输出的理解

java中的标准输入指的是System.in还是键盘输入&#xff1f;概念搞不太清楚&#xff0c;用Scanner类从键盘输入算是标准输入吗&#xff1f; 先理清一些概念&#xff1a;每个控制台程序都有标准输入、标准输出、标准错误输出三个管道&#xff08;句柄&#xff09;&#xff0c;这…

【FFmpeg】avcodec_open2函数

目录 1. avcodec_open21.1 编解码器的预初始化&#xff08;ff_encode_preinit & ff_decode_preinit&#xff09;1.2 编解码器的初始化&#xff08;init&#xff09;1.3 释放编解码器&#xff08;ff_codec_close&#xff09; FFmpeg相关记录&#xff1a; 示例工程&#xff…

Python数据分析-房价预测机器学习

一、研究背景 房地产市场作为经济活动的关键领域之一&#xff0c;对于经济的发展和社会的稳定起着至关重要的作用。在当今全球化和信息化的背景下&#xff0c;房地产市场的波动和房价的变化不仅受到国内因素的影响&#xff0c;还受到全球经济环境和国际政治形势等外部因素的影…

深入理解ThreadLocal原理

以下内容首发于我的个人网站&#xff0c;来这里看更舒适&#xff1a;https://riun.xyz/work/9898775 ThreadLocal是一种用于实现线程局部变量的机制&#xff0c;它允许每个线程有自己独立的变量&#xff0c;从而达到了线程数据隔离的目的。 基于JDK8 使用 通常在项目中是这样…

JS爬虫实战之Fastmoss

Fastmoss参数逆向 逆向前准备思路1- 确认接口2- 参数确认3- 重试校验参数逻辑4- 寻找逆向入口1- 方式一&#xff08;search搜索&#xff09;&#xff1a;2- 方式二&#xff08;堆栈搜索&#xff09;&#xff1a; 5- 获取加密算法1- fm-sign字段是有zn来的&#xff0c;我们查看z…

机器学习 C++ 的opencv实现SVM图像二分类的训练 (二)【附源码】

本节讲机器学习 C 的opencv实现SVM图像二分类的训练&#xff0c;下节讲测试&#xff1a; 数据集合data内容如下&#xff1a; 下载地址为&#xff1a;https://download.csdn.net/download/hgaohr1021/89506900 #include <stdio.h> #include <time.h> #include…

C语言课程回顾:六、C语言循环控制

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 C语言循环控制 6 循环控制6.1 概述6.2 goto语句以及用goto语句构成循环6.3 while语句6.4 do-while语句6.5 for语句6.6 循环的嵌套6.7 几种循环的比较6.8 break和continue语句…

Windows系统安装NVM,实现Node.js多版本管理

目录 一、前言 二、NVM简介 三、准备工作 1、卸载Node 2、创建文件夹 四、下载NVM 五、安装NVM 六、使用NVM 1、NVM常用操作命令 2、查看NVM版本信息 3、查看Node.js版本列表&#xff1b; 4、下载指定版本Node.js 5、使用指定版本Node.js 6、查看已安装Node.js列…

Java知识点整理 18 — Lambda表达式

一. 简介 Lambda 表达式是函数式编程思想的体现&#xff0c;强调做什么&#xff0c;而不是以什么方式去做。 面向对象编程思想强调的是对象&#xff0c;必须通过对象的形式来做一些事情。比如多线程执行任务&#xff0c;需要创建对象&#xff0c;对象需要实现指定接口&#x…

Rust监控可观测性

可观测性 在监控章节的引言中&#xff0c;我们提到了老板、前端、后端眼中的监控是各不相同的&#xff0c;那么有没有办法将监控模型进行抽象、统一呢&#xff1f; 来简单分析一下&#xff1a; 业务指标实时展示&#xff0c;这是一个指标型的数据( metric )手机 APP 上传的数…

若依 ruoyi vue上传控件 el-upload上传文件 判断是否有文件 判断文件大小

console.info(this.$refs.upload.uploadFiles.length)//this.$refs.upload.uploadFiles.length 获取当前上传控件中已选择的文件大小//判断是否存在已上传文件 if(this.$refs.upload.uploadFiles.length 0){this.$modal.msgWarning("请上传文件");return; }

轻松配置,无需重复操作:PyCharm新建项目后,如何让当前新建项目使用既有虚拟环境

1、点击右上角的设置按钮 2、点击Settings 3、点击profect 4、点击python Interprter&#xff0c;这个是python解释器 5、点击 add interpreter&#xff0c;这个是增加python解释器 6、再点击add Local interpreter 7、选择第一个Virtualenv Environment,然后选择Existin…