这篇文章讨论一下与链表的环相关的题目,我目前遇到的一共有3种题目。

1.判断一个链表是否有环(LeetCode相关题目:https://leetcode.com/problems/linked-list-cycle/description/)

设置两个指针,初始值都指向头,一快一慢,slow每次前进一步,fast每次前进两步,假如链表存在环,两个指针必定会相遇。假如fast走到尾部,则为无环链表。

代码如下:

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *fast = head;
ListNode *slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (slow == fast) {
return true;
}
}
return false;
}
};

2.判断一个有环链表中环的位置(LeetCode相关题目:https://leetcode.com/problems/linked-list-cycle-ii/description/)

也是利用到一快一慢的两个指针,借用网上一个图:

两个指针顺时针走动,fast一次走两步,slow一次走一步,假设两个指针第一次在Z相遇,slow走过的距离为a+b,fast走过的距离为a+b+c+b,2(a + b) == a + b + c + b,得出a == c,因此此时将fast指针放回起点,将两次走一步改为一次走一步。此时,fast和slow同时开始走,由于他们的路程和速度都一样,因此他们会在环的起点相遇。

代码如下:

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head;
ListNode *fast = head;
while (true) {
if (fast == NULL || fast->next == NULL) return NULL;
else {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) break;
}
}
fast = head;
while (fast != slow) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
};

3.求两个链表的交点(LeetCode相关题目:https://leetcode.com/problems/intersection-of-two-linked-lists/description/)

尽管看上去和链表的环没啥关系,但是这个题目可以用这种方法来做。我们可以先将其中一个环的头尾相连,然后按照上一题的做法,就可以找到交点的位置了。不过要记得将一切复原,也就是将环解开。

代码如下:

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == NULL || headB == NULL) return NULL;
ListNode *copyA = headA;
ListNode *copyB = headB;
while (headA->next != NULL) {
headA = headA->next;
}
ListNode *recover = headA;
headA->next = copyA;
ListNode *fast = headB;
ListNode *slow = headB;
while (true) {
if (!fast || !fast->next) {
recover->next = NULL;
headA = copyA;
headB = copyB;
return NULL;
}
fast = fast->next->next;
slow = slow->next;
if (fast == slow) break;
}
fast = headB;
while (fast != slow) {
slow = slow->next;
fast = fast->next;
}
recover->next = NULL;
headA = copyA;
headB = copyB;
return slow;
}
};

4.其他的。。。

我能想到的其他题目类型:

求环的长度:在2的前提下,从环的起点开始,一个指针不动,一个指针走,统计走的长度,两个指针重新相遇时的长度就是环的长度

将环解开:原理其实一样

因此,这类题目的关键是利用一快一慢两个指针,然后要懂得找出环的起点的方法,其他变形的问题也就迎刃而解了。

环链表相关的题目和算法[LeetCode]的更多相关文章

  1. 算法<初级> - 第二章 队列、栈、哈希表相关问题

    算法 - 第二章 数据结构 题目一 用数组实现大小固定的队列和栈(一面题) 数组实现大小固定栈 /*** * size是对头索引(initSize是固定大小) 也是当前栈大小 * size=下个进队i ...

  2. 前端与算法 leetcode 26. 删除排序数组中的重复项

    目录 # 前端与算法 leetcode 26. 删除排序数组中的重复项 题目描述 概要 提示 解析 算法 # 前端与算法 leetcode 26. 删除排序数组中的重复项 题目描述 26. 删除排序数 ...

  3. 前端与算法 leetcode 350. 两个数组的交集 II

    目录 # 前端与算法 leetcode 350. 两个数组的交集 II 题目描述 概要 提示 解析 解法一:哈希表 解法二:双指针 解法三:暴力法 算法 # 前端与算法 leetcode 350. 两 ...

  4. 前端与算法 leetcode 283. 移动零

    目录 # 前端与算法 leetcode 283. 移动零 题目描述 概要 提示 解析 解法一:暴力法 解法二:双指针法 算法 传入[0,1,0,3,12]的运行结果 执行结果 GitHub仓库 # 前 ...

  5. 前端与算法 leetcode 1. 两数之和

    目录 # 前端与算法 leetcode 1. 两数之和 题目描述 概要 提示 解析 解法一:暴力法 解法二:HashMap法 算法 传入[1, 2], [11, 1, 2, 3, 2]的运行结果 执行 ...

  6. 前端与算法 leetcode 48. 旋转图像

    目录 # 前端与算法 leetcode 48. 旋转图像 题目描述 概要 提示 解析 解法一:转置加翻转 解法二:在单次循环中旋转 4 个矩形 算法 传入测试用例的运行结果 执行结果 GitHub仓库 ...

  7. 前端与算法 leetcode 7. 整数反转

    目录 # 前端与算法 leetcode 7. 整数反转 题目描述 概要 提示 解析 解法 算法 传入测试用例的运行结果 执行结果 GitHub仓库 # 前端与算法 leetcode 7. 整数反转 题 ...

  8. 前端与算法 leetcode 8. 字符串转换整数 (atoi)

    目录 # 前端与算法 leetcode 8. 字符串转换整数 (atoi) 题目描述 概要 提示 解析 解法一:正则 解法二:api 解法二:手搓一个api 算法 传入测试用例的运行结果 执行结果 G ...

  9. 前端与算法 leetcode 387. 字符串中的第一个唯一字符

    目录 # 前端与算法 leetcode 387. 字符串中的第一个唯一字符 题目描述 概要 提示 解析 解法一:双循环 解法二:Set法单循环 算法 传入测试用例的运行结果 执行结果 GitHub仓库 ...

随机推荐

  1. 模仿J2EE的session机制的App后端会话信息管理

    此文章只将思想,不提供具体完整实现(博主太懒,懒得整理),有疑问或想了解的可以私信或评论 背景 在传统的java web 中小型项目中,一般使用session暂存会话信息,比如登录者的身份信息等.此机 ...

  2. angular 使用概术

    框架技术细节说明 must 该文档详细说明了基于Angular的机制及关键技术. 目录: - 路由机制 - 通过路由来切分页面模块 - Lazyload机制 - 指令 - 程序bootstrap - ...

  3. C# 跨平台的支付类库ICanPay

    随着微软的开源,越来越多的项目支持跨平台,但是各种支付平台提供的类库,又老又不支持跨平台,吐槽下,尤其是微信,还有好多坑,于是ICanPay诞生了,今天就来讲ICanPay是什么,怎么使用? ICan ...

  4. Java学习笔记12---向上转型-父类的对象引用指向子类对象

    当父类的对象引用没有指向父类的对象,而是指向了子类的对象时,调用方法或访问变量时会怎样呢? 假设父类为Person,子类为Student,有下面的两行定义: Student sTest = new S ...

  5. 关于tolua的使用

    一.首先在引擎的跟目录下找到cocos2d-x自带的工具tolua++ 二.使用tolua++生成自定义类的声明 打开tool文件夹中的readme文件如下: 1. Generating the lu ...

  6. 【OCR技术系列之一】字符识别技术总览

    最近入坑研究OCR,看了比较多关于OCR的资料,对OCR的前世今生也有了一个比较清晰的了解.所以想写一篇关于OCR技术的综述,对OCR相关的知识点都好好总结一遍,以加深个人理解. 什么是OCR? OC ...

  7. Less循环

    Less循环 在Less中,mixin可以调用它自身.通过这种递归调用,再结合Guard表达式和模式匹配,就可以写出各种循环结构.如,使用循环来创建一个网格类: .generate-columns(4 ...

  8. Serializable 都这么牛逼了,Parcelable 还要你何用?

    一些闲聊 距离上一篇文章似乎又是很久了,看起来也没有很多反馈,催更就更不用说了.哈哈,放弃了. 话说最近公司在招聘一批至少 5 年开发经验的 Android 开发工程师,我也是忙开了花,激动得不行呀. ...

  9. Thinkphp导入外部类的方法

    相信很多人在使用TP时候都苦恼使用外部类各种不成功 下面为大家详细介绍下引用方法和注意细节 手动加载第三方类库 由于第三发类库没有具体的命名空间,所以需要使用以下几种方法手动导入 1.import方法 ...

  10. poj1611 解题报告

    并查集学习过之后做了几道相关联系,这里贴出1611 The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions:  ...