指针的面试题

news2024/11/13 8:35:14

这里写目录标题

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

判断链表中是否有环

题目

描述

判断给定的链表中是否有环。如果有环则返回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.coloradmin.cn/o/1952841.html

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

相关文章

Java语言程序设计——篇九(1)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 内部类 概述内部类—内部类的分类成员内部类实战演练 局部内部类实战演练 匿名内部类实战演练 静态内部类实战演练 概述 内部类或嵌套类&#…

不支持jdk8的jenkins部署jdk8项目

1、背景 目前最新的jenkins必须基于jdk8以上&#xff0c;才能安装。jenkins最新的插件部分也不支持jdk8了。 2、全局工具配置 配置一个jdk8 配置一个jdk8以上的版本&#xff0c;如jdk17 3、部署maven项目 jdk17项目 可以直接使用maven插件&#xff0c;部署。 jdk8项目 由…

Zenario CMS 9.2 文件上传漏洞(CVE-2022-23043)

前言 CVE-2022-23043 是一个影响 Zenario CMS 9.2 的严重漏洞。该漏洞允许经过身份验证的管理员用户绕过文件上传限制。具体来说&#xff0c;管理员可以通过创建一个新的带有 ".phar" 扩展名的“文件/MIME 类型”&#xff0c;然后上传一个恶意文件。在上传过程中&am…

运维锅总详解NFS

NFS是什么&#xff1f;如何对NFS进行部署及优化&#xff1f;NFS工作流程是什么&#xff1f;NFS的性能及优缺点是什么&#xff1f;NFS发展历史又是怎样的&#xff1f;希望本文能帮您解答这些疑惑&#xff01; 一、NFS简介 NFS (Network File System) 是由 Sun Microsystems 在…

【最新】cudnn安装教程

最近换了新电脑需要重新安装cuda和cudnn&#xff0c;发现现在cudnn的安装比以前方便多了&#xff0c;直接在官网下载exe安装包一键运行即可。安装的时候注意cuda和cudnn的对应关系即可&#xff1a;【最新】cuda和cudnn和显卡驱动的对应关系-CSDN博客 访问cudnn下载链接cuDNN 9…

docker-compose 根据yaml拉取镜像出问题

在学习go微服务时&#xff0c;用docker-compose启动nacos以及对应的mysql时出现上面的问题&#xff0c; 使用的yaml如下 version: "3.8" services:nacos:image: nacos/nacos-server:${NACOS_VERSION}container_name: nacos-standalone-mysqlenv_file:- ../env/cust…

SpringCloud+Vue3多对多,多表联查

♥️作者&#xff1a;小宋1021 &#x1f935;‍♂️个人主页&#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…

c/c++的内存管理(超详细)

一、c/c的内存分布 这是操作系统中对于内存的划分&#xff1a; 我们重点掌握以下几个区域即可&#xff1a; 1.栈 (调用函数会建立栈帧) 2.堆(动态开辟的空间) 3.数据段(静态区)&#xff1a;存放静态变量以及全局变量 4.代码段 (常量区) 先来看看一个题目&#xff1a; int…

JDK的配置

安装好JDK后&#xff0c;配置三个环境变量 第一步&#xff0c;配置JAVA_HOME. 先找到JDK的安装目录&#xff0c;然后复制路径&#xff0c;在电脑的环境变量里增添变量名为JAVA_HOME,变量值为 C:\Program Files\Java\jdk1.8.0_192。&#xff08;具体根据你的JDK安装路径&…

Lombok的认识

Lombok的作用 Lombok是一个Java库&#xff0c;它可以通过简单的注解形式来帮助开发人员简化Java代码的编写&#xff0c;特别是减少模板代码的书写。具体来说&#xff0c;Lombok的主要作用包括&#xff1a; 减少模板代码&#xff1a;Lombok可以通过注解自动生成getter、setter、…

Python——Pandas(第三讲)

文章目录 修改替换变量值对应数值的替换指定数值范围的替换 虚拟变量变换数值变量分段数据分组基于拆分进行筛选 分组汇总使用 agg 函数进行汇总引用自定义函数 长宽格式转换转换为最简格式长宽型格式的自由互转 多个数据源的合并数据的横向合并concat 命令 处理缺失值认识缺失…

【Apache Doris】3.0存算分离|标准部署篇(一)

【Apache Doris】3.0存算分离&#xff5c;标准部署篇&#xff08;一&#xff09; 一、前提概要二、环境信息三、前置准备四、FoundationDB安装五、OpenJDK 17安装六、 Meta Service安装七、集群安装八、快速体验 接上 数据架构新篇章&#xff1a;存算一体与存算分离的协同演进。…

Meta 发布Llama 3.1开源模型 NVIDIA推出AI 代工服务

在这周二&#xff0c;Meta发布了最新的AI模型Llama 3.1&#xff0c;并且是一个开源模型&#xff0c;面向公众免费提供&#xff0c;且提供8B、70B、305B参数版本&#xff0c;模型整体效果可与 GPT-4、GPT-4o、Claude 3.5 Sonnet 等领先的闭源模型相媲美。 此次Llama 3.1 系列改…

Hadoop3.3.5的安装与单机/伪分布式配置

文章目录 一、安装须知二、安装jdk三、安装shh四、安装配置hadoop五、运行hadoop 一、安装须知 本次安装的Hadoop版本为hadoop3.3.5。 在这之前完成了VMware虚拟软件的安装&#xff0c;并安装了Ubuntu22.04&#xff0c;在这基础上进行相关配置。 二、安装jdk 在Ubuntu中使用…

顺序表算法题

在学习了顺序表专题后&#xff0c;了解的顺序表的结构以及相关概念后就可以来试着完成一些顺序表的算法题了&#xff0c;在本篇中将对三道顺序表相关的算法题进行讲解&#xff0c;希望能对你有所帮助&#xff0c;一起加油吧&#xff01;&#xff01;&#xff01; 1.移除元素 2…

Lago - 使用 ClickHouse 扩展事件引擎

本文字数&#xff1a;4540&#xff1b;估计阅读时间&#xff1a;12 分钟 作者&#xff1a;Mathew Pregasen 本文在公众号【ClickHouseInc】首发 本周&#xff0c;我们欢迎来自 Lago 的一篇博客文章&#xff0c;介绍了他们如何使用 ClickHouse 扩展一个事件引擎&#xff0c;并在…

【JavaEE精炼宝库】 网络编程套接字——初识网络编程 | UDP数据报套接字编程

文章目录 一、网络编程基础1.1 网络编程的意义&#xff1a;1.2 网络编程的概念&#xff1a;1.3 网络编程的术语解释&#xff1a;1.4 常见的客户端服务端模型&#xff1a; 二、Socket 套接字2.1 Socket 套接字的概念&#xff1a;2.2 Socket 套接字的分类&#xff1a; 三、UDP数据…

24暑假算法刷题 | Day21 | LeetCode 669. 修剪二叉搜索树,108. 将有序数组转换为二叉搜索树,538. 把二叉搜索树转换为累加树

目录 669. 修剪二叉搜索树题目描述题解 108. 将有序数组转换为二叉搜索树题目描述题解 538. 把二叉搜索树转换为累加树题目描述题解 669. 修剪二叉搜索树 点此跳转题目链接 题目描述 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪…

Mac应用快速启动器:Alfred 5 for Mac 激活版

Alfred 5 是一款专为 macOS 系统设计的效率提升工具。这款软件以其快速启动和高效操作功能著称&#xff0c;通过使用快捷键来呼出输入界面&#xff0c;用户可以快速完成各种任务。 最新版本 Alfred 5.5 引入了一些新功能。其中包括整合了 ChatGPT 和 DALL-E&#xff0c;这意味…

Map的常见API

Map的常见API Map是双列集合的顶层接口&#xff0c;它的功能是全部双列集合都可以继承使用的 Map的遍历方式 map的遍历方式(键找值) package demo3;import java.util.HashMap; import java.util.Map; import java.util.Set;public class a1 {public static void main(String…