算法通关村第一关-链表黄金挑战笔记|环的入口

news2024/11/28 4:40:25

解决链表环入口问题


文章目录

  • 解决链表环入口问题
  • 前言
    • 链表中环的问题
      • Hash和集合的解法:
      • 快慢指针实现解决:
    • 解题思路:
      • Hash或者使用集合的方式实现
      • 快慢指针(这里使用三次刚好解决)
  • 总结


前言

提示:无论今天过得如何,就当穿了一天的袜子,回家就脱了吧。

当然解决这个问题之前,我们需要了解一个概念,就是链表的有环是怎么判断的,定义是什么?
废话不多说,直接上图片💕

在这里插入图片描述
在这个A链表中,我们就看出他是存在环的

  1. 有环
  2. 节点 4 就是环的入口

这就引出来另一个问题了,怎么判断链表有环❔

链表中环的问题

当然拿到这个问题,思考的话(最快想到的解决方法就是Hash[map]),下来就是采用集合呗🥰,虽然这样的话可以很快解决,有点儿逃避链表的嫌疑😒

Hash和集合的解法:

遍历链表,一次将数据元素存入map中,是要是发现有相同的元素,就说明链表中有环,代码实现起来也很简单。

/**
 * 方法1:通过HashMap判断
 *
 * @param head
 * @return
 */
public static boolean hasCycleByMap(ListNode head) {
    // 一般条件下不改变head的位置
    ListNode pos = head;
    HashMap<ListNode,Integer> map = new HashMap();
    while(pos != null) {
        if(!map.containsKey(pos)){
            map.put(pos,null);
        }else{
            return true;
        }
        pos = pos.next;
    }
    return false;
}

使用集合的话,思想和上面👆类似,这里就不在重复了,直接上代码😂

/**
     * 方法1:通过HashSet判断
     *
     * @param head
     * @return
     */
    public static boolean hasCycleByMap(ListNode head) {
        // 保留一下头节点的位置
        ListNode pos = head;
        HashSet<ListNode> set = new HashSet<>();
        while (pos != null) {
        // if (set.contains(pos)){  // 这里也可以只用set判断
        //     return true;
        // }else{
        //      set.add(pos);
        // }
            if(!set.add(pos)){
                return true;
            }
            pos = pos.next;
        }
        return false;
    }

那么不逃离链表,就是使用链表需要怎么解决呢?思考(三分钟💡)
常见的算法解决 双指针 呗

快慢指针实现解决:

这里快慢指针要怎么理解呢?
我们类比一个场景:就是在一个圆形的操场上跑步,一个同学跑的快,一个同学跑的慢,经过一段时间后,必然会存在两人相遇的情况,况且正好是快的同学比慢的同学多跑一圈。
这里就可以建立数学模型

  1. 两位通过起始地点相同 快同学 v1 慢同学 v2(目前可以这样称呼 😂起名字很纠结ahhah)
  2. 经过相同的时间相遇 经过时间 t
  3. 假设围绕操场一圈的长度是 s
 s = (v1 -v2)t

这里放到链表里面就好办多了,我们就可以让fast走一步,然后fast和slow同时出发,如果后面出现fast和slow相遇,那就说明链表里面存在环呀🥰,这不就吧问题解决了。那我们就写一下代码吧。

/**
 * 方法2 通过双指针实现
 *
 * @param head
 * @return
 */

public static boolean hasCycleByTwoPoint(ListNode head) {
    // 校验参数
    if(head == null || head.next == 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;
}

解题思路:

Hash或者使用集合的方式实现

最简单的办法就是Hash呗,当然使用集合也不是不行(Set)。这就不在赘述了,显得就有点啰嗦啦🤣

快慢指针(这里使用三次刚好解决)

解决了链表有环的问题,我们再来看看怎么确定链表的环形入口在哪里❔(思考一下💡)
我们再来看这个环的图:
在这里插入图片描述
当然如果链表是这样的话也是一样的:

在这里插入图片描述

解决思路💕:

  1. 确定链表有环 (上面我们已经解决了)
  2. 确认链表的长度(这里可以相遇的时候 固定一个fast节点 让slow继续前行直到再次相遇 就可以得出环的长度 这里我们就简单的设置为 k )
  3. 确定环的入口(当我们从链表的后面往前看的话 链表环的入口刚好是倒数第 k 个节点。

有了思路那么实现起来就比较容易了🤩,下面就是代码的展示环节了😂

/**
 * 方法2 通过双指针实现
 *
 * @param head
 * @return
 */

public static ListNode detectCycleByTwoPoint(ListNode head) {
    // 校验参数
    if (head == null || head.next == null){ // 链表想要成环至少需要两个节点
        return null;
    }
    ListNode fast = head, slow = head;
    // 确定链表有环
    while(fast != null && fast.next != null){
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow){// 说明有环
            // 确认链表的长度
            int count = 1;
            slow = slow.next;
            while (fast != slow){
                count++;
                slow = slow.next;
            }
            // 确定环的入口
            fast = head;
            slow = head;
            int temp = count;
            while(temp >0){
                fast = fast.next;
                temp--;
            }
            while (count >0){
                fast = fast.next;
                slow = slow.next;
                count--;
            }
            return slow;
        }
    }
    return null;
}

总结

提示:链表环的问题是比较经典的问题,重点理解 链表环的入口问题

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

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

相关文章

AI绘画Stable Diffusion原理之Autoencoder-Latent

前言 传送门&#xff1a; stable diffusion&#xff1a;Git&#xff5c;论文 stable-diffusion-webui&#xff1a;Git Google Colab Notebook&#xff1a;Git kaggle Notebook&#xff1a;Git 今年AIGC实在是太火了&#xff0c;让人大呼许多职业即将消失&#xff0c;比如既能帮…

Windows 10 安装 PostgreSQL教程

前言 本文写于2023年7月26日&#xff0c;经过本人实测&#xff0c;目前安装PostgreSQL 15.3版本有很多问题&#xff0c;百度测试过解决方法&#xff0c;暂无成功。因此建议安装低一点的版本。如PostgreSQL 14.8版本。以下记录我的安装过程&#xff0c;供大家参考。 下载地址 …

Ceph版本

每个Ceph的版本都有一个英文的名称和一个数字形式的版本编号 第一个 Ceph 版本编号是 0.1&#xff0c;发布于2008 年 1月。之后是0.2,0.3....多年来&#xff0c;版本号方案一直没变。 2015年 4月0.94.1 (Hammer 的第一个修正版) 发布后&#xff0c;为了避免 0.99 (以及 0.100…

Linux Day02

目录 一、Linux系统文件类型与文件权限 1、文件类型 3.修改文件权限---chmod 1.文字设定 二、Linux常用命令 1、基础命令 1.1 pwd 1.2 cd 1.3 ls 1.4 touch 1.5 mkdir 1.6 rmdir ​1.7 rm -r 1.8 cp 1.9 mv 2、文件查看命令 2.1 cat 2.2 more 2.3 less 2.4 hea…

【MySQL】不允许你不知道如何插入数据

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集 &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0…

Python numpy库的应用、matplotlib绘图、opencv的应用

numpy import numpy as npl1 [1, 2, 3, 4, 5]# array():将列表同构成一个numpy的数组 l2 np.array(l1) print(type(l2)) print(l2) # ndim : 返回数组的轴数&#xff08;维度数&#xff09; # shape&#xff1a;返回数组的形状&#xff0c;用元组表示&#xff1b;元组的元素…

Redis数据库的9种数据类型与数据持久化

系列文章传送门&#xff1a; 【七天入门数据库】第一天 MySQL的安装部署 【七天入门数据库】第二天 数据库理论基础 【七天入门数据库】第三天 MySQL的库表操作 【七天入门数据库】第四天 数据操作语言DML 一、Redis的9种数据类型的基本操作 &#xff08;一&#xff09;k…

在家下载论文使用哪些论文下载工具比较好

在家下载论文如果不借助论文下载工具是非常艰难的事情&#xff0c;因为很多查找下载论文的数据库都是需要账号权限才可使用的。 例如&#xff0c;我们查找中文论文常用的知网、万方等数据库以及众多国外论文数据库。 在家下载知网、万方数据库论文可用下面的方法&#xff1a;…

备战秋招 | 笔试强训15

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、在公有派生的情况下&#xff0c;派生类中定义的成员函数只能访问原基类的(&#xff09; A. 公有成员和私有成员 B. 私有成员和保护成员 C. 公有成员和保护成员 D. 私有成员,保护成员和公有成员 2…

基于Docker-compose创建LNMP环境并运行Wordpress网站平台

基于Docker-compose创建LNMP环境并运行Wordpress网站平台 1.Docker-Compose概述2.YAML文件格式及编写注意事项3.Docker-Compose配置常用字段4.Docker Compose常用命令5.使用Docker-compose创建LNMP环境&#xff0c;并运行Wordpress网站平台1. Docker Compose 环境安装下载安装查…

Spring 的元注解

一、元注解介绍 1.1.源码引入 1.2.元注解介绍 从上面的图片可知&#xff0c;Spring 有四个【负责注解其他注解】的元注解&#xff0c;分别是&#xff1a; Target&#xff1a;标识该注解可以用于标注哪些程序元素&#xff0c;比如类、方法、字段等。 Retention&#xff1a;标…

【PS教程-环境搭建】

下载地址 安装教程 软件安装包下载解压打开。找到Set-up应用程序双击运行安装。点击继续&#xff0c;或者你需要更改安装位置。软件正在安装中。软件安装成功。安装完成&#xff0c;打开软件使用。 通道抠图&#xff08;主体颜色不能和背景相近&#xff09; 抠图攻略 首先…

重学C++系列之const与static关键字分析

前言 本篇幅讲解关键字const与static&#xff0c;主要围绕在类的范围内叙述&#xff0c;包括作用和使用场景等。 一、const与static的作用 1、const修饰的成员变量&#xff0c;成员变量初始化后不能再修改。 2、const修饰的成员函数&#xff0c;成员函数不可以修改成员变量&am…

063、故障处理之快速恢复数据

数据丢失快速恢复的重要性 目的&#xff1a;尽快修复数据&#xff0c;恢复业务 快速恢复相关技术对比 常用备份恢复技术 数据快速恢复原理 MVCC 是TiDB数据库原生的一项功能&#xff0c;默认使用无需配置&#xff0c;它使用多个历史快照的方式来维护数据在某个时间点对并…

五步快速搭建个性化外卖小程序商城

随着人们生活节奏的加快&#xff0c;外卖行业蓬勃发展。为了满足用户的需求&#xff0c;许多企业开始使用小程序商城来提供外卖服务。那么&#xff0c;如何制作一个功能完善、用户友好的外卖小程序商城呢&#xff1f;下面就来为大家详细介绍一下制作的步骤。 首先&#xff0c;我…

【深度学习】以图搜索- facebook的faiss 从环境搭建到运行案例从0到1

文章目录 前言安装小试牛刀项目延伸总结 前言 Faiss的全称是Facebook AI Similarity Search。 这是一个开源库&#xff0c;针对高维空间中的海量数据&#xff0c;提供了高效且可靠的检索方法。 暴力检索耗时巨大&#xff0c;对于一个要求实时人脸识别的应用来说是不可取的。 …

当深度强化学习(DRL)遇见图神经网络(GNN)

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在学习摘录和笔记专…

day02.数组

一,数组 数组:一组有序的相同类型数据的集合 1.1声明数组: 数组元素类型 数组名【】;数组元素类型【】 数组名; 🎃more : 数组元素类型【】【】数组名;注:Java的数组是先声明对象再分配空间(而C语言是声明数组的同时指明了数组的长度,给数组分配了…

fastadmin采坑之接口分页处理

其实不算fastadmin的代码而是thinkphp自带的分页代码 paginate函数就是自带的分页函数&#xff0c;开始我以为这个只能用于渲染模板不能用于接口&#xff0c;后面看到源代码发现请求参数带page就可以 /*** ApiTitle (获取协会会员)* ApiSummary (获取协会会员)* ApiMethod …

买卖股票的最佳时机系列

//方法一 class Solution { public:int dp[100005];int maxProfit(vector<int>& prices) {//dp[i]表示前i天买入卖出的获取的最大利润//min_val表示前i-1天买入的最小值&#xff1b;dp[0]0;int min_valprices[0];for(int i1;i<prices.size();i){dp[i]max(dp[i-1],…