C++快慢指针理解与应用

  • 原理
  • 应用
    • 有序链表中寻找中位数
  • 判断链表是否存在环,如果存在,找到环入口
  • 判断两个单链表是否相交,如果相交找到他们的第一个公共节点

原理

快慢指针中的快慢指的是移动的步长,即每次向前移动的快慢,例如每次可以让快指针沿链表向前移动2,慢指针向前移动1次。

应用

有序链表中寻找中位数

  快指针移动的速度是慢指针移动速度的两倍,因此当快指针到达链表尾部的时候,慢指针刚好到达中点。
  程序还要考虑链表节点个数的奇偶数因数,当快指针移动x次后到链表尾 1 + 2 x 1+2x 1+2x,说明链表有奇数个节点,直接返回慢指针指向的数据即可。
  如果快指针是倒数第二个结点,说明链表结点个数是偶数,这时可以根据“规则”返回上中位数或下中位数或(上中位数+下中位数)的一半。

while(fast && slow){if(fast->next == NULL){return slow->data;}else if(fast->next != NULL && fast->next->next == NULL){return (slow->data + slow->next->data)/2;}else{fast = fast->next->next;slow = slow->next;}
}

判断链表是否存在环,如果存在,找到环入口

  有一个单链表,其中可能有一个环,也就是某个节点的next指向的是链表中在它之前的节点,这样在链表尾部形成一个环。
  如果判断一个链表是否存在一个环?设定两个指针slow,fast,均从头指针开始,每次分别前进1步、2步。如果存在环,则两者相遇;如不存在环,fast遇到NULL退出。
  如果链表存在环,如果找到环的入口点?当fast与slow相遇时,slow肯定没有遍历完链表或者恰好遍历一遍。于是我们从链表头与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,则相遇的第一个点为环入口点。

node* findLoopPort(node *head) {node *fast;node *slow;while (fast && fast->next) {    //第一步:判断链表是否存在环slow = slow->next;fast = fast->next->next;if (slow == fast) {break;}}if ((fast == NULL) || (fast ->next == NULL)) {   //链表不存在环return NULL;}//第二步:寻找环的入口点slow = head;  //让slow回到链表的起点,fast留在相遇点while (slow != fast) {  //当slow和fast再次相遇,那个点就是环的入口点slow = slow->next;fast = fast->next;}reurn slow;
}

判断两个单链表是否相交,如果相交找到他们的第一个公共节点

  判断两个链表是否相交,如果相交,给出相交的第一个点(假设两个链表不存在环)。
思路:
  首先利用快慢指针判断链表是否存在环。
  (a)如果不存在环,则如果两个单向链表有公共节点,也就是两个链表从某一节点开始,他们的p_next都指向同一个节点,每一个节点只有一个p_next。因此从第一个公共节点开始,之后他们所有节点都是重合的。因此,首先两个链表先遍历一次,求两个链表的长度分别是L1、L2,然后可以得到他们的长度差L。然后先在长的链表上遍历L个节点,之后再同步遍历,于是在遍历中,第一个相同节点就是第一个公共节点。此时,若两个链表长度分别是M、N,则时间复杂度为O(M+N)。

  • 如果两个指针没有环且相交于一个节点,这个节点后面都是共有的。所以如果两个链表相交,那么两个链表的结尾节点的地址也是一样的。程序实现时分别遍历两个单链表,直到尾结点。判断尾结点地址是否相等即可。时间复杂度为O(L1+L2)。
  • 如果找到第一个相交的节点?判断是否相交的时候,记录两个链表的长度,算出长度差len,接着先让较长的链表遍历len个长度,然后两个链表同时遍历,判断是否相等,如果相等,就是第一个相交的节点。
void Is_2List_Intersect(LinkList L1, LinkList L2){if (L1 == NULL || L2 == NULL) {exit(ERROR);}LinkList p = L1;LinkList q = L2;int L1_length = 0;int L2_length = 0;int len = 0;while (p->next) {L1_length++;p = p->next;}while (q->next) {L2_length++;q = q->next;}printf("p: = %d\n", p);printf("q: = %d\n", q);printf("L1_length: = %d\n", L1_length);printf("L2_length: = %d\n", L2_length);if (p ==q) {printf(" 相交\n")/*p重新指向短的链表 q指向长链表*/if (L1_length > L2_length) {len = L1_length - L2_length;p = L2;q = L1;} else {len = L2_length - L1_length;p = L1;q = L2;}while (len) {q = q->next;len--;}while (p != q) {p = p->next;q = q->next;  }printf("相交的第一个结点是:%d\n",p->data);} else {printf("不相交\n");}
}

  (b)如果一个存在环,另一个不存在环,则这两个链表是不可能相交的。
  (c)如果利用快慢指针发现两个链表都存在环,则判断任意一个链表上快慢指针相遇的那个节点,在不在另外一个链表上,如果在,则相交,不在,则不相交。

C++快慢指针理解与应用相关推荐

  1. 双指针算法之快慢指针(一):力扣【判断链表是否有环】leetcode-141、142

    一.简介:什么是快慢指针? 快慢指针,顾名思义,无非就是设置一个快指针,一个慢指针,初始化的时候,快指针和慢指针都指向链表的头结点,前进的时候一个在前一个在后,结合起来可以十分巧妙的解决链表中的一些问 ...

  2. 【LeetCode笔记】287. 寻找重复数(Java、快慢指针、原地、链表)

    文章目录 题目描述 思路 & 代码 更新 题目描述 可以理解成数组版本的 环形链表 II 更多详细思路可见以上超链接. 思路 & 代码 如何转化成逻辑上的链表? nums[i] 是 第 ...

  3. 试编写一个将双向循环链表逆置的算法_图解:链表的快慢指针,解决 80% 的链表面试题!...

    一.前言 链表是基本的数据结构之一,它与数组不同,数组在内存中存储,需要一块连续的内容空间来存储,对内存的要求比较高.例如我们需要 100MB 大小的数组,内存中就必须有一段连续的 100MB 的内存 ...

  4. 快慢指针(LeetCode寻找重复数),弗洛伊德的乌龟和兔子

    写此篇博客在于总结,记忆之用,欢迎评论补充. 弗洛伊德的乌龟和兔子,即快慢指针. 对于LeetCode287题,寻找重复数,题目如下: 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 ...

  5. python数据结构,快慢指针

    最近听的b站左程云数据结构,记录下来题和代码,python实现 链表 快慢指针 题目1:返回链表的第一个环结点,没有环就返回空 题目2:判断两个链表有没有共同结点,返回第一个共同结点,在没有环的情况下 ...

  6. 快慢指针判断链表是否有环

    链表中很经常会出现的一个问题,判断链表是否有环,标准答案也已经烂熟于心,设置快慢指针,快指针每次走2步,慢指针每次走1步,如果两个指针可以相遇的话,证明链表有环,反之无环. 我有时候就犯嘀咕,它俩一定 ...

  7. 一文学会链表快慢指针解题技巧

    前言 上文 我们详细地学习了链表的基本概念,优缺点,也带大家一步步由浅入深地学习了链表的翻转技巧,这一篇我们来看看链表的另一个解题技巧:快慢指针. 快慢指针在面试中出现的概率也很大,也是务必要掌握的一 ...

  8. 动画:链表快慢指针解题技巧

    点击蓝色"五分钟学算法"关注我哟 加个"星标",天天中午 12:15,一起学算法 作者 | 码海 前言 这一篇我们来看看链表的另一个解题技巧:快慢指针. 快慢指 ...

  9. 尝试证明快慢指针可以相遇问题 以及 证明入环点问题

    预热 引用题目:环形链表 快慢指针解法: class Solution {public boolean hasCycle(ListNode head) {if(head == null) {retur ...

最新文章

  1. 别在 Java 代码里乱打日志了,这才是正确的打日志姿势!
  2. 溢出漏洞利用小结(基础)
  3. 关于学习Python的一点学习总结(56->random的使用)
  4. 8088/8086的功能结构
  5. pyspark dataframe数据连接(join)、转化为pandas dataframe、基于多个字段删除冗余数据
  6. 风险管理、收尾管理、知识产权管理
  7. Python-爬取2345电影并写入文件
  8. C++(STL):28 ---关联式容器map用法
  9. 2018年计算机CPU纳米制程,联发科疯狂堆核计划曝光:7纳米制程,12核CPU
  10. 前端开发必备:js中的sort()排序函数
  11. lms自适应滤波器实现噪声干扰的语音恢复_使用VoiceFliter-Lite改进设备上的语音识别...
  12. android 3d模型ppt,PPT已支持3D PPT怎么插入3D模型?
  13. 关于创建 LINQ to SQL 类时无法转换复数的问题(zhuan)
  14. 2015/12/12 考了PAT,又回来玩Python了。
  15. 制造行业IT运维管理解决方案
  16. Bernoulli-Gaussian分布
  17. 2013计算机核心期刊,2013年度发表国内核心期刊论文
  18. c语言自定义sum函数,c语言自定义函数
  19. 财务分析就是财务报表分析吗?
  20. Monitor对象是什么?

热门文章

  1. 申请上计算机课的申请,诺丁汉大学计算机学院课程申请通道将即将关闭,抓紧上车了...
  2. [Python] reverse()函数 VS reversed()函数
  3. Android实现渐色变圆形
  4. 超链接 番茄札记 html,番茄学习法笔记以及初始尝试
  5. 爬动的蠕虫(C语言)
  6. vue项目权限:数据权限、菜单权限、按钮权限
  7. 远程视频专家系统,指导系统方案整理
  8. win7拔掉耳机后电脑没声音了
  9. 一目了然——二叉树的遍历(先序,中序,后序遍历)
  10. Nginx: 正向与反向代理