“快慢指针”思想在物理或者逻辑循环中的应用

1 基础概念

1.1 什么是物理循环和逻辑循环?

物理循环是指物理索引访问顺序上相邻,逻辑上也相邻,比如循环链表,逻辑循环则指物理的索引上不一定相邻

1.2 快慢指针本质上可以解决逻辑循环问题,而物理循环也属于逻辑循环问题。

2 用快慢指针找出物理循环

2.1 LC141. 环形链表

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head==null||head.next==null)return false;
        ListNode f=head;
        ListNode s=head;

        while(f!=null&&f.next!=null){
            f=f.next.next;
            s=s.next;
            if(f==s){
                return true;
            }
        }
        return false;
    }
}

3 用快慢指针找出逻辑循环

3.1 LC457. 环形数组是否存在循环

在这里插入图片描述

3.1.1 解析

务必参考题解:快慢指针解法

class Solution {
    public boolean circularArrayLoop(int[] nums) {
        int n=nums.length;
        for(int i=0;i<n;i++){
            if(nums[i]==0)continue;
            int s=i;
            int f=next(nums,i);
            while(nums[s]*nums[f]>0&&nums[s]*nums[next(nums,f)]>0){
                if(s==f){
                    if(s!=next(nums,s)){
                        return true;
                    }else{
                        break;
                    }
                }
                s=next(nums,s);
                f=next(nums,next(nums,f));
            }

            int add=i;

            while(nums[add]*nums[next(nums,add)]>0){
                nums[add]=0;
                add=next(nums,add);
            }
        }
        return false;
    }
    int next(int nums[],int i){
        int n=nums.length;
        return ((i+nums[i])%n+n)%n;
    }
}

3.1.2 Q1:针对这道题,为什么可以用快慢指针呢?快慢指针本身不是针对链表嘛?而且每次只能走一步啊

您的疑问是非常合理的。快慢指针方法通常用于链表环路检测,但其实它也可以适用于这种环形数组问题。这里的关键在于理解快慢指针方法的本质:它是一种用于检测循环或周期性的算法。

在环形数组问题中,即使每次移动的步数不是一步,我们仍然可以使用快慢指针。在这个问题中,"快指针"每次移动两个nums[i]的距离,而"慢指针"每次移动一个nums[i]的距离。这种设置保证了如果存在一个循环,快指针最终会追上慢指针。这就是为什么可以使用快慢指针方法来解决这个问题。

具体到这个问题:

  • 每个元素nums[i]指示从当前位置应该移动的步数,正数表示向前移动,负数表示向后移动。
  • 环形数组意味着数组是循环的,即从数组末尾的下一个元素是数组开头的元素。
  • 快慢指针在这里是用来检测循环的存在。如果存在一个循环,那么快指针最终会在某个点上追上慢指针。
  • 在追踪快慢指针的过程中,还需要考虑移动的方向。如果在移动过程中方向改变(即从正转负或从负转正),则当前路径不构成有效循环。

因此,尽管这个方法最初是为链表设计的,但其检测循环的基本原理在环形数组问题中同样适用。

3.1.3 Q2:这里的步数是指逻辑上位置的步数对吧?

是的,您理解得正确。在这个环形数组问题中,"步数"指的是逻辑上位置的步数。具体来说:

  • 数组中的每个元素 nums[i] 表示从位置 i 出发应该移动的步数。
  • 如果 nums[i] 是正数,则表示向前(即下标递增的方向)移动 |nums[i]| 步。
  • 如果 nums[i] 是负数,则表示向后(即下标递减的方向)移动 |nums[i]| 步。
  • 由于数组是环形的,所以到达数组的末端后会再次从头开始,反之亦然。

在这个问题的上下文中,步数并不是指物理意义上的步行距离,而是指在数组索引上的移动距离。例如,如果 nums[i] = 3,则意味着从索引 i 向前移动3个索引位置。由于是环形数组,当超过数组末端时,计数会从数组开头继续。

3.1.4 Q3:对于快慢指针而言,只要存在环,无论快和慢指针的的初始位置怎么变,最终快慢可以相遇对吗(解释代码中slow和fast初始位置为什么设置的不同)

是的,对于快慢指针法来说,只要存在环,快指针最终都会追上慢指针,从而使两者相遇。这个结论是基于以下几个关键点的:

  1. 不同速度:快指针的移动速度是慢指针的两倍。这意味着如果存在一个环,快指针每轮会逐渐接近慢指针。

  2. 循环性:由于环的存在,快慢指针都会不断地绕环运动。这确保了,只要存在环,快慢指针永远不会“走出”环并停止。

  3. 相遇条件:快慢指针在环中的相对位置每次循环都会变化。由于快指针每次循环比慢指针多走一圈,它们最终必然会在某个点相遇。

这些原则不仅适用于链表中的环检测,也同样适用于类似的环形数组问题。关键是环的存在以及快慢指针的相对速度差。在实际应用中,初始位置一般会从一个固定点开始,例如数组的起始位置,以确保能够覆盖所有可能的环。

3.4.5 (1) 在环中,如果让快指针走三步,慢指针走1步,也最终能相遇吗?(2) 在环中,如果让快指针走三步,慢指针走2步,也最终能相遇吗

在环形结构中,快慢指针是否能相遇取决于它们的相对速度差,而不仅仅是它们各自的速度。我们来分析一下您提出的两种情况:

  1. 快指针每次走三步,慢指针每次走一步:在这种情况下,快指针和慢指针之间的相对速度差是两步。这意味着如果存在一个环,快指针最终会追上慢指针。这是因为快指针每次循环都会逐渐接近慢指针,并最终在某个点与慢指针相遇。

  2. 快指针每次走三步,慢指针每次走两步:在这种情况下,快指针和慢指针之间的相对速度差是一步。这同样意味着如果存在一个环,快指针仍然会最终追上慢指针。虽然这种情况下快慢指针相遇的时间可能会比速度差更大的情况更长,但只要环存在,它们最终还是会相遇。

总结来说,只要快慢指针之间存在速度差,它们就会在环中最终相遇。速度差越大,相遇的可能性就越快出现。在实际应用中,通常选择让快指针的速度是慢指针的两倍,这样可以在保证检测效率的同时简化问题的复杂度。

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

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

相关文章

【java】toString() 导致的 StackOverflowError 异常

这是怎么导致的呢&#xff1f; A 类属性包含着 B 类的引用 B 类属性包含着 A 类的引用 代码大概就是这样的&#xff1a; Data public class User{public String name;public Dog dog; }Data public class Dog{public String name;public User user; }User user new User()…

面试前自测题,接口自动化测试过程中怎么处理接口依赖?

面试的时候经常会被问到在接口自动化测试过程中怎么处理接口依赖&#xff1f; 首先我们要搞清楚什么是接口依赖。 01、什么是接口依赖 接口依赖指的是&#xff0c;在接口测试的过程中一个接口的测试经常需要依赖另一个或多个接口成功请求后的返回数据。 那怎么处理呢&#…

机器学习---使用 EM 算法来进行高斯混合模型的聚类

1. 指定k个高斯分布參数 导包 import math import copy import numpy as np import matplotlib.pyplot as pltisdebug False 全局变量 isdebug可以用来控制是否打印调试信息。当 isdebug 为 True 时&#xff0c;代码中的一些调试信 息将被打印出来&#xff0c;方便进行调试…

Kubernetes(k8s)访问不了Pod服务

在k8s集群部署java web应用的服务时&#xff0c;浏览器访问不了pod服务或linux终端curl http://192.168.138.112:30000即curl http://ip地址:端口号失败&#xff0c;如下图&#xff1a; 在网上找了很久的答案&#xff0c;最后还是没解决&#xff0c;后来突然想起来一直是在k8…

7个简单技巧,让你从容应对压力面试!

01-什么是压力面试&#xff1f; 压力面试是指有意制造紧张&#xff0c;以了解求职者将如何面对工作压力的一种面试形式。 事实上&#xff0c;压力面试不是单独存在的一类面试&#xff0c;往往是穿插在面试过程中。 面试人通过提出不礼貌、冒犯的问题&#xff0c;或者用怀疑、…

JavaWeb(五)

一、JDBC概述 JDBC 就是使用Java语言操作关系型数据库的一套API 全称是Java DataBase Connectivity 表示Java数据库连接。 JDBC的本质是官方&#xff08;sun公司&#xff09;定义的一套操作所有关系型数据库的规则&#xff0c;即接口,各个数据库厂商去实现这套接口&#xff0…

11、信息打点——红队工具篇FofaQuakeSuize水泽Arl灯塔

网络空间测绘引擎 Fofa Quake shodan Zoomeye 主要搜关联资产、特征资产、资产信息&#xff08;在测绘引擎上直接搜IP&#xff0c;它会显示所有与该域名有关的信息。&#xff09; fofa和Quake测绘引擎集成化工具&#xff1a;Finger 自动化信息收集项目 ARL灯塔 Suize水泽 …

编程语言分类

如果要将编程语言分成两大类&#xff0c;可以考虑以下分类方式&#xff1a; 编译型语言&#xff08;Compiled Languages&#xff09;&#xff1a;这类语言在运行之前需要通过编译器将源代码转换为机器码或类似形式的可执行代码。编译型语言的特点包括&#xff1a; 需要显式的编…

二极管:TVS瞬态抑制二极管

一、什么是TVS二极管 TVS&#xff08;Transient Voltage Suppressors&#xff09;&#xff0c;即瞬态电压抑制器&#xff0c;又称雪崩击穿二极管。 TVS二极管的符号如下图所示 什么是雪崩击穿 雪崩击穿是有必要了解一下的&#xff0c;不然后面还有齐纳击穿&#xff0c;搞不…

GoWin FPGA--- startup2

clock Click Tools\IP Core Generator\rPLL, and open the configure file 原语 for Clock 双击选项&#xff0c;生产对应的代码&#xff0c;Copy到制定的地点。 右侧有对应的说明文件

【优选算法系列】【专题一双指针】第三节.611. 有效三角形的个数和LCR 179. 查找总价格为目标值的两个商品

文章目录 前言一、有效三角形的个数 1.1 题目描述 1.2 题目解析 1.2.1 算法原理 1.2.2 代码编写 1.2.3 题目总结二、查找总价格为目标值的两个商品 2.1 题目描述 2.2 题目解析 2.2.1 算法原理 …

FastAPI与BaseModel

from typing import Optionalfrom fastapi import FastAPI from pydantic import BaseModel #当一个模型属性具有默认值时&#xff0c;它不是必需的。否则它是一个必需属性。将默认值设为 None 可使其成为可选属性 app FastAPI() class Item(BaseModel):name:str #没有初始值都…

动态类型语言与静态类型语言的对比与比较

编程语言可以根据类型系统和类型检查时机分为动态编程语言和静态编程语言两大类&#xff0c;它们在运行时的代码检查方式、变量类型的使用方式等方面有很大的区别。这一块你知道吗&#xff1f; 本文将为您详细讲解两种编程语言的优缺点&#xff0c;以及它们的应用场景。 动态编…

基于SpringBoot的校园互助网站

简介 本系统分为三个角色&#xff0c;分别是普通用户和管理员、以及超级管理员&#xff0c;主要的功能模块有注册、登录、物品代购、快递代取、话题管理、任务管理、反馈管理、投诉管理、订单管理等功能模块。 项目 数据库 首页 登录 新增反馈 发布话题 发布任务 接单 我要投诉…

Windows下使用AndroidStudio及CMake编译Android可执行程序或静态库动态库

Windows下使用AndroidStudio及CMake编译Android可执行程序或静态库动态库 文章目录 Windows下使用AndroidStudio及CMake编译Android可执行程序或静态库动态库一、前言二、编译环境三、示例C/CPP程序1、总体工程结构2、示例代码3、CMakeLists.txt&#xff08;重要&#xff09;4、…

深入理解URL、URI和URN在Web开发中的重要性

引言&#xff1a; 在Web开发中&#xff0c;我们经常听到URL、URI和URN这几个术语&#xff0c;它们是构建和理解互联网资源的基础。虽然它们看起来相似&#xff0c;但实际上代表着不同的概念。本文将深入研究URL、URI和URN的定义、用途以及在Web开发中的重要性。 一、什么是URI&…

Verilog基础:$time、$stime和$realtime系统函数的使用

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html $time、 $stime和$realtime这三个系统函数提供了返回当前仿真时间方法。注意&#xff0c;这里的仿真时间的最小分辨能力是由仿真时间精度决定的&#xff0c;简单来说&#xff0c;可以理解为…

Oracle连接错误:ORA-28040:没有匹配的验证协议

一、产生原因&#xff1a;oci动态库版本太低&#xff0c;无法连接高版本的数据库 二、解决办法 1、下载高版本的oci库 https://www.oracle.com/database/technologies/instant-client/winx64-64- downloads.html 2、解压并复制oci动态库 3、粘贴到相应的目录

VSCode + gdb + gdbserver调试ARM程序

在开发ARM嵌入式端C/C程序时&#xff0c;一般会在PC上编写代码&#xff0c;在Linux服务器上编译&#xff0c;然后将程序复制或挂载到ARM开发板上运行。如果程序出了问题&#xff0c;在不使用gdb的情况下&#xff0c;经常在代码中添加打印&#xff0c;编译&#xff0c;然后在开发…

CentOS 7 安装并配置tomcat

简介 Tomcat是一个使用Java编写的开源Web应用服务器,是由Apache Software Foundation管理的一个项目。它是一个轻量级的应用服务器,可以下载、安装和使用,而且还提供了许多高级功能,例如支持Java Servlet、JavaServer Pages (JSP)和JavaServer Faces (JSF) 等JavaEE技术,…