指针的面试题

这里写目录标题

  • 判断链表中是否有环
    • 描述
    • 代码
      • 检测链表中是否存在环
      • 链表中存在环
      • 想检测链表中是否存在环,而不需要找到环的入口

判断链表中是否有环

题目

描述

判断给定的链表中是否有环。如果有环则返回true,否则返回false。

数据范围:链表长度 0≤n≤10000,链表中任意节点的值满足

∣val∣<=100000
要求:空间复杂度 O(1),时间复杂度 O(n)

输入分为两部分,第一部分为链表,第二部分代表是否有环,然后将组成的head头结点传入到函数里面。-1代表无环,其它的数字代表有环,这些参数解释仅仅是为了方便读者自测调试。实际在编程时读入的是链表的头节点。

例如输入{3,2,0,-4},1时,对应的链表结构如下图所示:
在这里插入图片描述

可以看出环的入口结点为从头结点开始的第1个结点(注:头结点为第0个结点),所以输出true。
示例1

输入: {3,2,0,-4},1

返回值: true

说明:第一部分{3,2,0,-4}代表一个链表,第二部分的1表示,-4到位置1(注:头结点为位置0),即-4->2存在一个链接,组成传入的head为一个带环的链表,返回true

示例2

输入:{1},-1

返回值:false

说明: 第一部分{1}代表一个链表,-1代表无环,组成传入head为一个无环的单链表,返回false

示例3

输入:{-1,-7,7,-4,19,6,-9,-5,-2,-5},6

返回值:true

代码

import java.util.*;/*** 定义了链表节点的类。* 每个节点包含一个整数值和一个指向下一个节点的引用。*/
class ListNode {int val; // 节点存储的值ListNode next; // 指向下一个节点的引用// 构造函数,用于创建一个新的节点,初始化其值和下一个节点的引用ListNode(int x) {val = x;next = null;}
}public class Solution {/*** 检测链表中是否存在环。* @param head 链表的头节点。* @return 如果链表中存在环,返回true;否则返回false。*/public boolean hasCycle(ListNode head) {// 如果头节点为空,则链表不存在环if (head == null) {return false;}// 初始化两个指针fast和slow,它们都指向头节点ListNode fast = head;ListNode slow = head;// 使用循环进行检测,直到fast和slow相遇或者fast到达链表末尾do {// 如果fast的下一个节点或者下下个节点为空,说明链表没有环if (fast.next == null || fast.next.next == null) {return false;}// 移动fast指针,每次移动两步fast = fast.next.next;// 移动slow指针,每次移动一步slow = slow.next;} while (fast != slow); // 如果fast和slow相遇,说明存在环// 如果循环结束,fast没有和slow相遇,说明链表没有环return true;}
}

检测链表中是否存在环

使用的是快慢指针(也称为龟兔赛跑算法)来检测链表中是否存在环。以下是快慢指针相遇的逻辑详细解释:

  1. 初始化:我们有两个指针fastslow,它们都从链表的头节点开始。

  2. 移动指针

    • fast指针每次移动两步(即fast = fast.next.next)。
    • slow指针每次移动一步(即slow = slow.next)。
  3. 相遇条件

    • 如果链表中存在环,那么fast指针和slow指针最终会相遇。这是因为fast指针移动的速度是slow指针的两倍,所以它们会在环内相遇。
    • 如果链表中没有环,fast指针会先到达链表的末尾(即fastfast.nextnull),此时fastslow不会相遇。
  4. 检测逻辑

    • 在每次循环中,我们首先检查fast指针的下一个节点或下下个节点是否为null。如果为null,则说明链表没有环,直接返回false
    • 如果fast指针的下一个节点或下下个节点不为null,则继续移动fastslow指针。
    • fastslow指针相遇时,说明链表中存在环,返回true
  5. 结束条件

    • 如果fast指针在移动过程中到达了链表的末尾(即fastfast.nextnull),则说明链表中没有环,返回false

通过这种方式,快慢指针算法能够有效地检测出链表中是否存在环,并且时间复杂度为O(n),空间复杂度为O(1)。


链表中存在环

如果链表中存在环,并且fastslow指针相遇,接下来的处理取决于你想要完成的具体任务。以下是一些常见的处理方式:

  1. 检测环的长度

    • 一旦fastslow相遇,你可以继续移动其中一个指针(通常是slow),每次移动一步,直到再次遇到环的起点。这样你可以计算出环的长度。
  2. 找到环的入口

    • 你可以在fastslow相遇后,将其中一个指针(通常是fast)重新指向头节点,然后同时移动fastslow,每次移动一步。当它们再次相遇时,相遇点就是环的入口。
  3. 删除环

    • 如果你的目标是删除环,可以在找到环的入口后,通过调整指针来删除环。例如,你可以将环的最后一个节点的next指针设置为null
  4. 重新初始化指针

    • 如果你只是需要检测环的存在,那么在fastslow相遇后,你可以直接返回true

以下是一些示例代码,展示如何在fastslow相遇后找到环的入口:

public class Solution {public boolean hasCycle(ListNode head) {if (head == null) {return false;}ListNode fast = head;ListNode slow = head;while (fast != slow) {if (fast == null || fast.next == null) {return false;}fast = fast.next.next;slow = slow.next;}// fast 和 slow 相遇,重新初始化 fast 指向头节点fast = head;// 当 fast 和 slow 再次相遇时,相遇点就是环的入口while (fast != slow) {fast = fast.next;slow = slow.next;}// 返回 true 表示链表中有环return true;}
}

在这个示例中,一旦fastslow相遇,我们将fast重新指向头节点,然后同时移动fastslow,直到它们再次相遇。这时的相遇点就是环的入口。这种方法可以确保你找到环的入口,而不仅仅是检测环的存在。


想检测链表中是否存在环,而不需要找到环的入口

如果你只想检测链表中是否存在环,而不需要找到环的入口,你可以简化代码,只保留检测环存在的逻辑。以下是修改后的代码示例:

public class Solution {/*** 检测链表中是否存在环。* @param head 链表的头节点。* @return 如果链表中存在环,返回true;否则返回false。*/public boolean hasCycle(ListNode head) {if (head == null) {return false;}// 初始化两个指针fast和slow,它们都指向头节点ListNode fast = head;ListNode slow = head;// 使用循环进行检测,直到fast和slow相遇或者fast到达链表末尾while (fast != null && fast.next != null) {// 移动fast指针,每次移动两步fast = fast.next.next;// 移动slow指针,每次移动一步slow = slow.next;// 如果fast和slow相遇,说明存在环if (fast == slow) {return true;}}// 如果fast到达链表末尾,说明没有环return false;}
}

在这个修改后的代码中,我们只保留了循环,直到fast指针到达链表的末尾或fastslow相遇。如果fastslow相遇,函数立即返回true,表示链表中存在环。如果fast到达链表的末尾(即fastfast.nextnull),则循环结束,函数返回false,表示链表中没有环。

这种方法的时间复杂度是O(n),空间复杂度是O(1),非常高效。

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

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

相关文章

Spring Boot集成canal快速入门demo

1.什么是canal&#xff1f; canal 是阿里开源的一款 MySQL 数据库增量日志解析工具&#xff0c;提供增量数据订阅和消费。 工作原理 MySQL主备复制原理 MySQL master 将数据变更写入二进制日志&#xff08;binary log&#xff09;, 日志中的记录叫做二进制日志事件&#xff…

二叉树_堆(下卷)

前言 接前面两篇的内容&#xff0c;接着往下讲二叉树_堆相关的内容。 正文 那么&#xff0c;回到冒泡排序与堆排序的比较。 我们知道冒泡排序的时间复杂度为 O ( N 2 ) O(N^2) O(N2)&#xff0c;这个效率是不太好的。 那么&#xff0c;我们的堆排序的时间复杂度如何呢&…

017、Vue动态tag标签

文章目录 1、先看效果2、代码 1、先看效果 2、代码 <template><div class "tags"><el-tag size"medium"closable v-for"item,index in tags":key"item.path":effect"item.title$route.name?dark:plain"cl…

数据结构 - AVL树

文章目录 一、AVL树的介绍二、AVL树的实现1、基本框架2、查找3、插入4、删除5、测试6、总代码 三、AVL树的性能 一、AVL树的介绍 1、概念 AVL树&#xff08;Adelson-Velsky and Landis Tree&#xff09;是一种自平衡的二叉搜索树。它得名于其发明者G. M. Adelson-Velsky和E. M…

Vue 状态管理 Vue CLI

Vue 状态管理 & Vue CLI 1、状态管理2、集中状态管理2.1 Vuex2.1.1 Vuex核心概念2.1.2 Vuex Store实例2.1.3 Vuex Getter2.1.4 Vuex Mutation2.1.4 Vuex Actions2.1.4 Vuex Module 2.2 Pinia2.2.1功能增强 3、Vuex 实现原理4、Pinia 实现原理5、CLI5.1 实现 1、状态管理 将…

【CG】计算机图形学(Computer Graphics)基础(其贰)

0 学习视频 B站GAMES101-现代计算机图形学入门-闫令琪 ※ 接上文【CG】计算机图形学&#xff08;Computer Graphics&#xff09;基础&#xff08;其壹&#xff09; 7 光线追踪 7.1 为什么需要光线追踪&#xff1f; 光栅化无法妥善处理全局效果 &#xff08;软&#xff09;阴…

一天搞定React(5)——ReactRouter(下)【已完结】

Hello&#xff01;大家好&#xff0c;今天带来的是React前端JS库的学习&#xff0c;课程来自黑马的往期课程&#xff0c;具体连接地址我也没有找到&#xff0c;大家可以广搜巡查一下&#xff0c;但是总体来说&#xff0c;这套课程教学质量非常高&#xff0c;每个知识点都有一个…

MATLAB基础:函数与函数控制语句

今天我们继续学习Matlab中函数相关知识。 API的查询和调用 help 命令是最基本的查询方法&#xff0c;可查询所有目录、指定目录、命令、函数。 我们直接点击帮助菜单即可查询所需的API函数。 lookfor 关键字用于搜索相关的命令和函数。 如&#xff0c;我们输入lookfor inpu…

开源物联网网关ThingsBoard IoT Gateway

前几天测试了Neuron&#xff0c;这是一个令人印象深刻的平台&#xff0c;不过它不能算是完全免费的平台&#xff0c;因为它还是有商业许可要求的&#xff0c;挺贵的&#xff0c;大几万的&#xff0c;而且它有走向闭源的趋势。所以也在寻找它的替代方案。 今天看到一个ThingsBo…

Django项目中报错:django.template.exceptions.TemplateDoesNotExist: index.html

访问127.0.0.1&#xff1a;8000访问出错 查看报错原因 到Django项目当中找到settings.py&#xff0c;找到TEMPLATES中的DIRS: 添加如下代码&#xff0c;并导入OS模块&#xff1a; "DIRS": [os.path.join(BASE_DIR,templates)] 再次访问IP地址&#xff1a;

C++(入门1)

C参考文档 Reference - C Reference C 参考手册 - cppreference.com cppreference.com 第一个C程序 #include<stdio.h> int main() {printf("Hello C\n");return 0; }由上述代码可知C是兼容C语言 第一个C标准程序 #include<iostream> using names…

【机器学习】智驭未来:机器学习如何重塑制造业的转型与升级

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f50d;1. 引言&#x1f4d2;2. 机器学习重塑制造业生产流程&#x1f338;预测性维护&#xff1a;减少停机时间&#xff0c;提高设…

实现共模噪声电流相互抵消的方法

共模传导路径中噪声电流相互抵消&#xff0c;从而使总的共模电流减小&#xff0c; 终达到降噪的目的。目前为实现共模噪声电流相互抵消&#xff0c;主要是采用动点电容抵消法。 动点电容抵消法原理 动点电容抵消法就是选取合适的动点&#xff0c;添加原副边跨接电容&#xff0c…

黑马头条Day10-定时计算热点文章、xxl-job

一、今日内容 1. 需求分析 目前实现的思路&#xff1a;从数据库直接按照发布时间倒序查询 问题&#xff1a; 如果访问量比较大&#xff0c;直接查询数据库&#xff0c;压力较大新发布的文章会展示在前面&#xff0c;并不是热点文章 2. 实现思路 解决方案&#xff1a;把热点…

CCS(Code Composer Studio 10.4.0)编译软件中文乱码怎么解决

如果是所有文件都出现了中文乱码这时建议直接在窗口首选项中修改&#xff1a;选择"Window" -> "Preferences"&#xff0c;找到"General" -> "Workspace"&#xff0c;将"Text file encoding"选项设置为"Other&quo…

深度解析Linux-C——函数和内存管理

目录 函数指针&#xff1a; 指针函数&#xff1a; 参数为指针的函数&#xff1a; 参数为数组的函数&#xff1a; C语言内存管理 stdlib.h头文件常用函数介绍 1、局部变量 2、全局变量 3、 堆空间变量 4、静态变量 5、常量 函数指针&#xff1a; 指向函数的指针&#…

Linux文件与相关函数的知识点3

main函数参数 int main(int argc,char *argv[]) { return 0; } C语言规定了main函数的参数只能有两个&#xff0c;一个是argc,一个是argv并且&#xff0c;argc只能是整数&#xff0c;第二个必须是指向字符 串的指针数组。 argc: 参数表示命令行中参数的个数&#xff0…

Java实现七大排序(二)

一.交换排序 1.冒泡排序 这个太经典了&#xff0c;每个学编程都绕不开的。原理跟选择排序差不多&#xff0c;不过冒泡排序是直接交换。 public static void bubbleSort(int[] array){for (int i 0; i < array.length - 1; i) {for (int j 0; j < array.length-1-i; j…

域内攻击手法——AS-REP Roasting攻击和Kerberoasting攻击

一、AS-REP Roasting攻击 1、AS-REP Roasting攻击原理 AS-REP Roasting是一种对用户账户进行离线爆破的攻击方式。但是该攻击方式使用上比较受限&#xff0c;因为其需要用户账户设置不要求Kerberos 预身份验证选项&#xff0c;而该选项默认是没有勾选的。Kerberos 预身份验证…

20240727 每日AI必读资讯

&#x1f310;OpenAI向Google宣战&#xff0c;重磅推出AI搜索引擎SearchGPT &#xff01; - 将 AI 与实时网络信息结合 提供生成式UI结果 - SearchGPT 结合网络最新信息可以直接回答问题&#xff0c;同时注明相关来源链接。 - 还可以像与人对话一样提出后续问题&#xff0c;…