浅谈快慢指针

article/2025/11/10 0:41:55

快慢指针

快慢指针

  • 快慢指针
  • 1.快慢指针的概念:
  • 2.快慢指针的应用:
    • 1. 判断单链表是否为循环链表
    • 2. 在有序链表中寻找中位数
    • 3.链表中倒数第k个节点

1.快慢指针的概念:

快慢指针就是存在两个指针,一个快指针,一个慢指针,两个指针每次移动的速度不一样,快的移动的快,慢的移动的慢。快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢。例如可以让快指针每次沿链表向前移动2,慢指针每次向前移动1次。

2.快慢指针的应用:

1. 判断单链表是否为循环链表

如果链表是单纯的环形链表我们的代码可以是这样的:
```javascript
bool isCLinkList(List *Head)
{List  *p = Head;while(p){p = p->next;if(p == Head){return true;}}return false;
}```

但是仔细一想这种办法只能判断链表为圆形的那种环形链表,就是头尾相连的那一种。

假如我们遇到了leecode的一道题,这种方法就一定不行了:
在这里插入图片描述

像这种链表的尾节点没有指向头结点的情况,它也是一种环形链表,我们应该怎么做呢?因为它不再经过头结点了,所以我们就不能用第一种方法了。
那么快慢指针的方法就是一种特别简单的方法了:

bool hasCycle(struct ListNode *head) {struct ListNode * slow = head;struct ListNode * fast = head;while (fast && fast -> next){slow = slow -> next;fast = fast -> next -> next;if (fast == slow){return true;}}return false;
}

定义两个指针,一个快指针,一个慢指针,快指针每次前进两步,慢指针每次前进一步,如果快指针追上了慢指针则说明这个链表是环形链表,如果没追上,则证明这个链表就是单链表。

快慢指针就好像两个人在赛跑,如果是在一个环形的跑道中,那么他们一直跑下去的话,快的就肯定能追上慢的,而且最少比慢的多跑了一圈。快慢指针判断环形链表就是这样的情况。

2. 在有序链表中寻找中位数

我们在看题之前先来做个游戏吧。
游戏的名字叫做烧火绳,游戏的规则是:烧一根不匀称的绳,从头烧到尾总共需要1个小时,现在有若干条材质相同的绳子,问如何用烧绳的方法来计时1个小时15分钟?
我的方法是:先取两绳,一绳一头烧,一绳两头同时烧。两头烧的绳烧完,是半小时,此时另一绳烧了一半,再烧另一头,烧完就是45分钟。烧完后再取一绳两头烧,烧完就是1小时15分。
其实,一根绳子两头烧就相当于是快指针,从一头烧就相当于慢指针,两头烧的绳子烧完的时候,一头烧的绳子烧了一半,就相当于快指针走完了,慢指针只走了一半。

所以如何在有序链表中寻找中位数呢?
我们需要定义两个指针,一个快指针,一个慢指针,因为链表为有序链表,所以我们控制快指针每次前进两步,慢指针前进一步,当快指针走到了链表的尾节点,慢指针就走到了链表的最中间了。另外此题还有一个陷阱就是:判断链表结点数量的奇偶性。如果我们的快指针移动了x次,如果达到了表尾的次数是(1 + 2x)则证明结点数量为奇数,则此时慢指针的值就是中位数。如果到达了链表的倒数第二个结点,则证明结点数量为偶数。则返回慢指针此时的值与下一个值的平均值。
代码如下:

int GetMedian(List *head)
{List *fast = *slow = head;while(fast && slow){if(fast == NULL){return slow -> data;}else if(fast -> next == NULL){return (double)(slow -> data + slow -> next -> data) / 2;}else{fast = fast -> next -> next;slow = slow -> next;}}
}

3.链表中倒数第k个节点

先看题:
在这里插入图片描述

这个题我们就可以使用快慢指针的方法,定义两个指针,想让第一个指针向前走k - 1步,然后在让快指针与慢指针同时向前移动,当快指针走到尾结点时,慢指针因为和快指针存在k - 1的距离所以此时慢指针就是倒数第k个结点。
代码如下:

struct ListNode* getKthFromEnd(struct ListNode* head, int k){if (k == 0 || head == NULL){return NULL;}struct ListNode *p = head;struct ListNode *q = head;int i;for (i = 0; i < k - 1; i++){p = p -> next;if (p == NULL){return NULL;}}while (p -> next != NULL){q = q -> next;p = p -> next;}return q;
}

这就是我本周分享关于快慢指针的内容,快慢指针在平时的应用最多的就是这三种题型,但是还有很多也可以应用快慢指针的思想,希望对大家有帮助。


http://chatgpt.dhexx.cn/article/0gRECbQ0.shtml

相关文章

快慢指针应用总结

快慢指针 快慢指针中的快慢指的是移动的步长&#xff0c;即每次向前移动速度的快慢。例如可以让快指针每次沿链表向前移动2&#xff0c;慢指针每次向前移动1次。 快慢指针的应用 &#xff08;1&#xff09;判断单链表是否存在环 如果链表存在环&#xff0c;就好像操场的跑道是…

十大常用经典排序算法总结!!!

爆肝整理&#xff01;堪称全网最详细的十大常用经典排序算法总结&#xff01;&#xff01;&#xff01; 写在开头&#xff0c;本文经过参考多方资料整理而成&#xff0c;全部参考目录会附在文章末尾。很多略有争议性的细节都是在不断查阅相关资料后总结的&#xff0c;具有一定…

经典五大算法思想-------入门浅析

算法&#xff1a;求解具体问题的步骤描述&#xff0c;代码上表现出来是解决特定问题的一组有限的指令序列。 1、分治&#xff1a; 算法思想&#xff1a;规模为n的原问题的解无法直接求出&#xff0c;进行问题规模缩减&#xff0c;划分子问题&#xff08;这里子问题相互独立而且…

算法设计经典算法

一、贪婪算法 1、概述 贪婪法又称贪心算法&#xff0c;是当追求的目标是一个问题的最优解时&#xff0c;设法把对整个问题的求解工作分成若干步骤来完成&#xff0c;是寻找最优解问题的常用方法。 贪婪法的特点是一般可以快速得到满意的解&#xff0c;因为它省去了为找最优解…

算法之经典图算法

图介绍表示图的数据结构图的两种搜索方式DFS可以处理问题BFS可以处理问题有向图最小生成树最短路径 图介绍 图&#xff1a;是一个顶点集合加上一个连接不同顶点对的边的集合组成。定义规定不允许出现重复边&#xff08;平行边&#xff09;、连接到顶点自身的边&#xff08;自环…

计算机10大经典算法

算法一&#xff1a;快速排序法 快速排序是由东尼霍尔所发展的一种排序算法。在平均状况下&#xff0c;排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较&#xff0c;但这种状况并不常见。事实上&#xff0c;快速排序通常明显比其…

算法设计——五大算法总结

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 算法设计总结 一、【分治法】二、【动态规划法】三、【贪心算法】四、【回溯法】五、【分支限界法】 一、【分治法】 在计算机科学中&#xff0c;分治法是一种很重要的算法。…

十大经典算法总结

正文 排序算法说明 &#xff08;1&#xff09;排序的定义&#xff1a;对一序列对象根据某个关键字进行排序&#xff1b; 输入&#xff1a;n个数&#xff1a;a1,a2,a3,...,an 输出&#xff1a;n个数的排列:a1,a2,a3,...,an&#xff0c;使得a1<a2<a3<...<an。 再…

九大经典算法

1. 冒泡排序&#xff08;Bubble Sort&#xff09; 两个数比较大小&#xff0c;通过两两交换&#xff0c;像水中的泡泡一样&#xff0c;较大的数下沉&#xff0c;较小的数冒起来。 算法描述&#xff1a; 1.比较相邻的元素。如果第一个比第二个大&#xff0c;就交换它们两个&a…

最常用的五大算法

一、贪心算法 贪心算法&#xff08;又称贪婪算法&#xff09;是指&#xff0c;在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整…

几种经典算法

1.分治法 分治法也叫做分而治之法。核心思想是将一个难以直接解决的大问题依照相同的概念分割成两个或者多个相同的小问题&#xff0c;以便各个击破。 如图所示&#xff1a; 2.递归法 递归法和分而治之法像一对孪生兄弟&#xff0c;都是将一个复杂的算法问题进行分解&#x…

五大常用经典算法—分治算法

原文作者&#xff1a;bigsai 原文地址&#xff1a;五大常用算法&#xff1a;一文搞懂分治算法 目录 前言 分治算法介绍 分治算法经典问题 二分搜索 快速排序 归并排序(逆序数) 最大子序列和 最近点对 结语 前言 分治算法&#xff08;divide and conquer&#xff09;是…

十大经典算法

十大经典排序算法&#xff08;动图演示&#xff09; 0、算法概述 0.1 算法分类 十种常见排序算法可以分为两大类&#xff1a; 非线性时间比较类排序&#xff1a;通过比较来决定元素间的相对次序&#xff0c;由于其时间复杂度不能突破O(nlogn)&#xff0c;因此称为非线性时间比…

OpenX系列标准:OpenDRIVE标准简述

1.概述 ​ 作为一个完整的仿真测试场景描述方案&#xff0c;OpenX系列标准包括&#xff1a;OpenDRIVE、OpenSCENARIO和OpenCRG。 标准文件格式文件内容OpenDRIVE.xodr静态部分&#xff08;如道路拓扑结构、交通标志标线等&#xff09;OpenDRIVE.tdo保存ROD项目时生成的文件&a…

OpenDRIVE坐标系解读

几种坐标系简述 opendrive标准主要包括三种坐标系&#xff1a;inertial(x, y, z)、reference line(s, t, h)、local(u, v, z) 下面这张图片笔者认为还是比较清晰的展示了三种坐标系的关系的&#xff1a; 惯性坐标系&#xff08;Inertial&#xff09; 惯性坐标系最简单&am…

《OpenDRIVE1.6规格文档》6

目录 12 标志12.1 针对标志的车道有效性12.2 标志依赖12.3 标志与物体之间的链接12.4 标志放置12.5 标志信息的复用12.6 控制器 13 铁路13.1 铁轨13.2 转辙器13.2.1 主轨道13.2.2 次轨道13.2.3 搭档转辙器 13.3 车站13.3.1 站台13.3.2 段 14 插图目录15 表格目录 12 标志 如图…

《OpenDRIVE1.6规格文档》4

目录 9.5.7 车道高度9.5.8 从道路超高程中排除车道 9.6 道路标识9.6.1 路标类型和线条9.6.2 显性路标类型和线条9.6.3 路标偏移 9.7 特定车道规则 10 交叉口10.1 来路10.2 联接道路10.2.1 交叉口中联接道路的优先级10.2.2 联接道路的方向 10.3 交叉口内的道路表面10.4 虚拟交叉…

opendrive地理坐标

通过使用基于PROJ&#xff08;一种用于两个坐标系之间数据交换的格式&#xff09;的投影字符串来完成对大地基准的描述。该数据应标为CDATA&#xff0c;因为其可能包含会干预元素属性XML语义的字符。 具体参数参考官方文档&#xff1a;Quick start — PROJ 9.2.0 documentatio…

OpenDRIVE地图图形化

OpenDRIVE地图图形化 前言一、 p l a n V i e w planView planView参数三次曲线弧线螺旋线 二、 e l e v a t i o n P r o f i l e elevationProfile elevationProfile三、 l a t e r a l P r o f i l e lateralProfile lateralProfile总结 前言 关于 O p e n D R I V E OpenD…

opendrive中的几何形状

道路的走向可以是多种多样的&#xff0c;可以是空旷地面上的直线、高速公路上细长的弯道、亦或山区狭窄的转弯。为从数学角度对所有这些道路线进行正确建模&#xff0c;OpenDRIVE提供了多种几何形状元素。 图19展示了五种定义道路参考线几何形状的可行方式&#xff1a; 直线螺…