这篇文章讨论一下与链表的环相关的题目,我目前遇到的一共有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. STM32学习方法

    1.网络学习资源 WWW.openedv.com      开源电子网 WWW.stmcu.org         ST中国官方技术网站,ST官方文档发布网站 微信公众平台             正 ...

  2. 使用AspectCore动态代理

    前言 最近越来越多的同学关注到AspectCore,并且提出不少中肯的建议,其中最多的提议是希望能够看到更多的关于AspectCore使用方式的文章和Demo.那么在这篇文章里,我们就来聊聊Aspec ...

  3. Android Oreo 8.0 新特性实战 Autosizing TextView --自动缩放TextView

    Android Oreo 8.0 新特性实战 Autosizing TextView --自动缩放TextView 8.0出来很久了,这个新特性已经用了很久了,但是一直没有亲自去试试.这几天新的需求来 ...

  4. TFboy养成记 tensorboard

    首先介绍几个用法: with tf.name_scope(name = "inputs"): 这个是用于区分区域的.如,train,inputs等. xs = tf.placeho ...

  5. vuejs(2.0)基础笔记

    基本结构 <div id="app"> {{ message }} </div> var app = new Vue({ el: '#wrap', data ...

  6. Meteor的初步了解

    最近入职到新一家公司,技术总监给我介绍了一个新技术---Meteor,这是我之前没有接触过的一项技术,我查阅了相关资料,原来这是一项基于Node js的纯Javascript技术,然后给了我们一个项目 ...

  7. lazy ideas in programming(编程中的惰性思想)

    lazy形容词,懒惰的,毫无疑问是一个贬义词.但是,对于计算机领域,lazy却是非常重要的优化思想:把任务推迟到必须的时刻,好处是避免重复计算,甚至不计算.本文的目的是抛砖引玉,总结一些编程中的laz ...

  8. PHP面向对象之const常量修饰符

    在PHP中定义常量是通过define()函数来完成的,但在类中定义常量不能使用define(),而需要使用const修饰符.类中的常量使用const定义后,其访问方式和静态成员类似,都是通过类名或在成 ...

  9. 责任链模式(Chain of Responsibility)

    责任链模式(Chain of Responsibility)接下来我们将要谈谈责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求 ...

  10. 分享一个好用的微信npmjs包

    https://www.npmjs.com/package/jquery_wechat_sdk 安装 $ npm install jquery_wechat_sdk 使用 Browser Script ...