数据结构学习--环形链表

news2024/11/18 8:59:19

环形链表

我们在判断一个链表是否是环形的,即首尾相连,我们可以以使用快慢指针,如果快指针能再次追上慢指针,就说明该链表是环形的,这边可以举个操场跑步的例子,当操场是环形的,跑的快的,就可以对跑的慢的实现套圈.

判断环形链表

给你一个链表,如果其是环形链表,则返回 true 否则返回 false

存放到集合中

分析:通过集合里面查找来判断是否回到头指针,不建议

public boolean hasCycle(ListNode head) {
    Set<ListNode> set = new HashSet<>();
    while (head != null) {
        //如果重复出现说明有环
        if (set.contains(head))
            return true;
        //否则就把当前节点加入到集合中
        set.add(head);
        head = head.next;
    }
    return false;
}

快慢指针(快2慢1)

package LinkList;

public class roundList {
    public class Solution {
        class ListNode {
            int val;
            ListNode next;

            public ListNode(int val, ListNode next) {
                this.val = val;
                this.next = next;
            }
        }
        public boolean hasCycle(ListNode head) {
            if (head == null){
                return false;
            }
            ListNode fast = head;
            ListNode slow = head;
            while (fast != null && fast.next != null){
                fast = fast.next.next;
                slow = slow.next;
                if (fast == slow){
                    return true;
                }
            }
            return false;
        }
    }
}

先反转再比较

如果反转过后的头结点与原来的头结点相同,那么就是环形链表
反转原理:

  1. 先给头结点的下个结点赋值一个新结点 temp
  2. 然后把头结点的 next 指向一个新节点 newHead
  3. 然后把那个新节点 newHead 指向 头结点
  4. 然后再令头结点 为 temp (之前头结点的下一个结点)
    在上面的流程中,temp充当相当于完成原来的链表的下个位置的指针,而newHead相当于是一种前驱指针的感觉,让原来在后面的元素指向前面的元素
public ListNode reverseList(ListNode head) {
        //新链表
        ListNode newHead = null;
        while (head != null) {
            //先保存访问的节点的下一个节点,保存起来
            //留着下一步访问的
            ListNode temp = head.next;
            //每次访问的原链表节点都会成为新链表的头结点,
            //其实就是把新链表挂到访问的原链表节点的
            //后面就行了
            head.next = newHead;
            //更新新链表
            newHead = head;
            //重新赋值,继续访问
            head = temp;
        }
        //返回新链表
        return newHead;
    }

    public boolean hasCycle(ListNode head) {
        ListNode rev = reverseList(head);
        if (head != null && head.next != null && rev == head) {
            return true;
        }
        return false;
    }

快慢指针的一般化

我们可以知道快指针要追上慢指针 需要多跑至少“一圈”,即一个链表长度,假设为m,当然所需要的时间就是 = 需要的圈数 / (快指针的速度 - 慢指针的速度)

为什么说多跑至少一圈?不妨想,快指针的速度 - 慢指针的速度 为偶数,而链表长度为奇数,那么就会出现第一次快指针追慢指针时,它们位置没有重合,而是快指针直接超越慢指针的情况,那么 快指针需要再追一圈,此时的圈数 = 2 * m,就一定为偶数就能追上

所以 所需要的时间就是 = 需要的圈数 / (快指针的速度 - 慢指针的速度) 必须为整数,当速度差分之圈数不是整数时,就需要多跑几圈来实现整除(即快慢指针的位置重合)

当然上面假设的环可能是从链表某处开始形成的环,有可能不是整个链表是环形
注意:循环的条件是快指针当前的不为null,如果要一次前进 m 步(即 fast = fast.m next)(m 个 next),那么就要保证其前面 m - 1个 next都不为null,否则会抛出空指针异常

代码(快3慢1)
ublic boolean hasCycle(ListNode head) {
        if (head == null)
            return false;
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next.next;
            if (slow == fast)
                return true;
        }
        return false;
    }
代码(快5慢1)
 public boolean hasCycle(ListNode head) {
        if (head == null)
            return false;
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null && fast.next.next != null && fast.next.next.next != null && fast.next.next.next.next != null) {
            slow = slow.next;
            fast = fast.next.next.next.next.next;
            if (slow == fast)
                return true;
        }
        return false;
    }
代码(快3慢2)
 public boolean hasCycle(ListNode head) {
        if (head == null)
            return false;
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null && fast.next.next != null) {
            slow = slow.next.next;
            fast = fast.next.next.next;
            if (slow == fast)
                return true;
        }
        return false;
    }

环形链表II

给你给定一个链表的头节点 head ,返回链表开始入环的第一个节点(在哪里开始形成环的)。 如果链表无环,则返回 null

分析

在这里插入图片描述
注:来源于魏梦舒老师的《算法漫画》
主要抓住两点,第一次相遇两指针的关系,一个走的路程是另外一个两倍

代码

public class roundListPlus {
    class ListNode{
        int val;
        ListNode next;

        public ListNode(int val) {
            this.val = val;
            next = null;
        }
    }
    public class Solution {
        public ListNode detectCycle(ListNode head) {
            ListNode fast = head;
            ListNode slow = head;
            // 快指针每次移动2,慢指针每次移动1
            // 用循环来寻找第一次相遇的点
            while (fast != null && fast.next != null){
                fast = fast.next.next;
                slow = slow.next;
                if (fast == slow){
                    break;
                }
            }
            // 循环结束要么是该表非环形,要么是快慢指针相遇
            // 判断,如果非环形链表,直接返回 null
            if ( fast == null || fast.next == null){
                return null;
            }
            // 根据递推关系,此时把其中一个指针放回头结点,另一个指针在第一次相遇位置
            // 此时两个指针一次都只移动1,下一次相遇就是入环结点
            slow = head;
            while (fast != slow){
                fast = fast.next;
                slow = slow.next;
            }
            return slow;
        }
    }
}

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

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

相关文章

Ansible组件说明

1.Ansible Inventory 工作当中有不同的业务主机&#xff0c;我们需要在把这些机器信息存放在inventory里面&#xff0c;ansible默认的inventory的文件是/etc/ansible/hosts&#xff0c;也可以通过ANSIBLE_HOSTS环境变量来指定或者运行ansible和ansible-playbook的时候用-i参数临…

泛微E9开发 快速隐藏明细表列

快速隐藏明细表列 1、隐藏列方法&#xff08;不作用&#xff0c;一直隐藏&#xff09; 在实际运用中&#xff0c;用户不需要但是需要间接使用的列&#xff0c;我们可以通过右击该列-【列自定义属性】-在“列自定义属性”菜单中启用“隐藏列”功能。 根据该方法设置的前端页…

纯js图片上传插件

目录标题 一、效果预览二、使用简单三、完整代码&#xff08;一&#xff09;index.html&#xff08;二&#xff09;css&#xff08;三&#xff09;js四、附带后台上传文件代码 一、效果预览 支持多图片上传&#xff0c;删除、预览。 二、使用简单 导入依赖&#xff08;需要…

视觉化数据的艺术:掌握Matplotlib基础绘图

Matplotlib基础绘图 文章目录 Matplotlib基础绘图1.基础流程2.绘图设置3.动态rc参数4.pyplot的基础图表函数 安利 1.基础流程 1.导入模块。绘图之前&#xff0c;需要先导入包含相应函数的模块。 2.创建画布与创建子图。第一部分主要是构建出一张空白的画布&#xff0c;如果需要…

Elastic 网络爬虫:为你的网站添加搜索功能

作者&#xff1a;来自 Elastic Lionel Palacin 为了演示如何使用 Elastic 网络爬虫&#xff0c;我们将以一个具体的网站为例&#xff0c;讲解如何在该网站上添加搜索功能。我们将探讨发现网站的方法&#xff0c;并利用 Elastic 网络爬虫提供的功能&#xff0c;以最佳方式准备待…

springboot+ssm基于Java的小型企业银行账目管理系统代码Lw

本毕业设计课题要求学生基于软件工程方法&#xff0c;根据课题的需求&#xff0c;给出小型企业银行账目管理系统概要设计、详细设计、数据库的设计以及系统实现和测试&#xff0c;并撰写规范的毕业设计说明书。该系统的主要模块有&#xff1a;系统管理、帐目管理、查询统计、用…

如何创建响应式HTML电子邮件模板

在这个适合初学者的指南中&#xff0c;你将学习如何创建一个响应式电子邮件模板。你将跟随逐步说明以及代码片段设计一个在任何设备上都看起来很棒的电子邮件模板。 这个项目非常适合渴望掌握电子邮件设计基础的新手&#xff01; &#xff08;本文视频讲解&#xff1a;java56…

抖店严查违规店铺!老商家下台,新手正是入驻时机!

哈喽~我是电商月月 抖店一直在严查违规店铺&#xff0c;很多新手都在犹豫不前&#xff0c;不知道要不要去做抖音小店 以为是抖音平台在“想方设法”克扣商家钱财&#xff0c;开店都是坑&#xff1f; 要这样想&#xff0c;那就大错特错了&#xff01; 抖店整改&#xff0c;把…

你的mongodb客户端是哪个呢?

MongoDB 是一种流行的文档数据库&#xff0c;它可以支持多种场景和应用。有很多客户端工具可以用来管理和操作 MongoDB&#xff0c;以下是一些常用的工具&#xff0c;以及它们的介绍&#xff1a; 一、MongoDB Shell MongoDB Shell 是连接&#xff08;和使用&#xff09;MongoD…

每日一题:计数质数

给定整数 n &#xff0c;返回 所有小于非负整数 n 的质数的数量 。 示例 1&#xff1a; 输入&#xff1a;n 10 输出&#xff1a;4 解释&#xff1a;小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。示例 2&#xff1a; 输入&#xff1a;n 0 输出&#xff1a;0示例 3&#…

NVIDIA智算中心“产品”上市,AI工业革命的iPhone时刻

GTC 2024落下帷幕了&#xff0c;但这个大会的信息仍在AI产业和经济中发酵。咨询机构WIKIBON认为&#xff0c;GTC 2024在整个科技史中的意义超过了当年史蒂夫乔布斯的iPod和iPhone发布。在AI将永久改变人类的共识下&#xff0c;GTC 2024在广度、愿景、生态系统等方面都有着深远影…

危险场景智能运维巡检系统

在石油、天然气、煤炭和化工等行业&#xff0c;特别是在I/IIC级防爆区场景中&#xff0c;存在着诸如易燃、易爆、高温、有毒有害以及粉尘等危险因素。例如&#xff0c;油气转运站、催化裂化装置、煤化工甲醇车间以及制氢站等地点&#xff0c;都面临着这些潜在的危险。传统的人工…

如何使用ArcGIS Pro进行路径分析

路径分析是一种空间分析技术&#xff0c;用于确定两个或多个地点之间最佳路径或最短路径&#xff0c;这里为大家介绍一下在ArcGIS Pro中如何进行路径分析&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的道路数据&#xff0c;除了道路数据&a…

交换基础配置--单臂路由

1、创建vlan 创建vlan10 创建vlan10和vlan20 创建vlan1到vlan9 vlan1可以不用创建&#xff0c;因为交换机的所有接口默认为vlan1 本实验只需要vlan10和vlan20&#xff0c;以上只是介绍创建vlan的方法。 查看创建的vlan&#xff1a; sw2同理。接着将需要划分vlan的接口划入…

linux基本命令2

一、Whereis是查找工具中速度最快的一个&#xff0c;但是whereis查找的范围有限&#xff0c; whereis只能查找2进制程序&#xff0c; 使用whereis查找 ls -b&#xff1a;查找2进制程序 -m&#xff1a;查找文档 -s&#xff1a;查找码源 二、which命令是查找工具中速度最快命令…

3D模型查看器开发实战【WebGL】

本文介绍如何从头开发一个包含3D 模型查看器的页面 - 尽管它非常简单&#xff0c;但你将学习的步骤也应该有助于构建其他类型的 Web 应用程序。 在自己的网站或博客里展示3D模型更简单的方式是使用NSDT 3DConvert提供的在线服务&#xff0c;无需任何开发工作&#xff0c;5分钟…

access多表关联提示:语法错误(操作符丢失)在查询表达式中

在access数据库中执行多表关联时提示了一个错误 select * from Patient a inner join BioMain b on a.BioIDb.BioID inner join BioResult c on b.BioIDc.BioID where len(a.PatientID)>12 and b.AddTime>#2024-04-17 05:53:23# and b.AddTime<#2024-04-17 17:53:23#…

基于Python 实现数据可视化大屏

数据本身是冰冷的数字&#xff0c;通过选择合适的图形或者图表来进行展示表达&#xff0c;使得传递给使用者的感受更加直观、更容易获得其中的价值。 数据可视化将技术与艺术完美结合&#xff0c;借助图形化的手段&#xff0c;清晰有效地传达与沟通信息。一方面&#xff0c;数…

Unity地形关联出错的解决办法以及地形深度拷贝

问题 最近发现unity地形系统的一个bug&#xff0c;导入的场景地形数据关联错乱了&#xff0c;关联到别的场景的地形数据了&#xff0c;meta替换了也没用&#xff0c;不清楚它具体是怎么关联的。 看下面的案例&#xff1a; 可以看到正常这个场景的地形数据应该关联的是Scene_E…

【GitBlit】Windows搭建Git服务器详细教程

前言 如果公司或个人想在 Windows 环境下搭建私有的 Git 服务器&#xff0c;那么这个开源的 GitBlit 是一个不错的选择。 Gitblit 是一个开源纯 Java 的用于管理、查看和服务 Git 存储库。它是一个小型的托管集中式存储库工具。支持 SSH、HTTP 和 GIT 协议&#xff0c;开箱即…