描述

给定一个链表,判断它是否有环。

样例

给出 -21->10->4->5, tail connects to node index 1,返回 true。

这里解释下,题目的意思,在英文原题中,tail connects to node index 1 表示的是节点 5 还要链接回索引号 为 1 的节点。

一个典型的带环链表如下:

挑战

不要使用额外的空间

代码

GitHub 的源代码,请访问下面的链接:

https://github.com/cwiki-us/java-tutorial/blob/master/src/test/java/com/ossez/lang/tutorial/tests/lintcode/LintCode0102HasCycleTest.java

package com.ossez.lang.tutorial.tests.lintcode;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.ossez.lang.tutorial.models.ListNode; /**
* <p>
* 102
* <ul>
* <li>@see <a href=
* "https://www.cwiki.us/display/ITCLASSIFICATION/Linked+List+Cycle">https://www.cwiki.us/display/ITCLASSIFICATION/Linked+List+Cycle</a>
* <li>@see<a href= "https://www.lintcode.com/problem/linked-list-cycle/">https://www.lintcode.com/problem/linked-list-cycle/</a>
* </ul>
* </p>
*
* @author YuCheng
*
*/
public class LintCode0102HasCycleTest { private final static Logger logger = LoggerFactory.getLogger(LintCode0102HasCycleTest.class); /**
*
*/
@Test
public void testMain() {
logger.debug("BEGIN");
// INIT LINKED LIST
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4); // CREATE A LOOP
head.next.next.next.next = head.next.next.next; boolean retResult = false; // LIKED LIST MAY NULL:
if (!(head == null || head.next == null)) {
ListNode s = head;
ListNode f = head.next; while (f.next != null && f.next.next != null) { s = s.next;
f = f.next.next; if (f == s) {
retResult = true;
break;
}
}
} System.out.println(retResult); }
}
 

点评

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接(”links”)。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的访问往往要在不同的排列顺序中转换。而链表是一种自我指示数据类型,因为它包含指向另一个相同类型的数据的指针(链接)。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。

要判断一个链表中是否有循环,可以借助额外的存储空间,将链表插入到 HashSet 中。创建一个以节点ID为键的HashSet集合,用来存储曾经遍历过的节点。然后同样是从头节点开始,依次遍历单链表的每一个节点。每遍历到一个新节点,就用新节点和HashSet集合当中存储的节点作比较,如果发现HashSet当中存在相同节点ID,则说明链表有环,如果HashSet当中不存在相同的节点ID,就把这个新节点ID存入HashSet,之后进入下一节点,继续重复刚才的操作。

这个方法在流程上和方法一类似,本质的区别是使用了HashSet作为额外的缓存。

假设从链表头节点到入环点的距离是D,链表的环长是S。而每一次HashSet查找元素的时间复杂度是O(1), 所以总体的时间复杂度是1*(D+S)=D+S,可以简单理解为O(N)。而算法的空间复杂度还是D+S-1,可以简单地理解成O(N)。

也可以采用指针的方式。

首先创建两个指针1和2(在java里就是两个对象引用),同时指向这个链表的头节点。然后开始一个大循环,在循环体中,让指针1每次向下移动一个节点,让指针2每次向下移动两个节点,然后比较两个指针指向的节点是否相同。如果相同,则判断出链表有环,如果不同,则继续下一次循环。

例如链表A->B->C->D->B->C->D,两个指针最初都指向节点A,进入第一轮循环,指针1移动到了节点B,指针2移动到了C。第二轮循环,指针1移动到了节点C,指针2移动到了节点B。第三轮循环,指针1移动到了节点D,指针2移动到了节点D,此时两指针指向同一节点,判断出链表有环。

此方法也可以用一个更生动的例子来形容:在一个环形跑道上,两个运动员在同一地点起跑,一个运动员速度快,一个运动员速度慢。当两人跑了一段时间,速度快的运动员必然会从速度慢的运动员身后再次追上并超过,原因很简单,因为跑道是环形的。

https://www.cwiki.us/display/ITCLASSIFICATION/Linked+List+Cycle

[LintCode] Linked List Cycle(带环链表)的更多相关文章

  1. lintcode:带环链表

    带环链表 给定一个链表,判断它是否有环. 解题 定义两个指针p1 p2 p1每次向前走一步 p2每次向前走两步 当p2能赶上p1的时候说明有环 /** * Definition for ListNod ...

  2. [LintCode] Linked List Cycle 单链表中的环

    Given a linked list, determine if it has a cycle in it. ExampleGiven -21->10->4->5, tail co ...

  3. [LeetCode] Linked List Cycle II 单链表中的环之二

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...

  4. [算法][LeetCode]Linked List Cycle & Linked List Cycle II——单链表中的环

    题目要求 Linked List Cycle Given a linked list, determine if it has a cycle in it. Follow up: Can you so ...

  5. [Leetcode] Linked list cycle ii 判断链表是否有环

    Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull. Follo ...

  6. [LeetCode] 142. Linked List Cycle II 单链表中的环之二

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To r ...

  7. [PHP] 算法-请找出带环链表的环的入口结点的PHP实现

    给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null 1.找链表倒数第k个结点,输入一个链表,输出该链表中倒数第k个结点.第一个指针走(k-1)步,到达第k个节点,两个指针同时往后 ...

  8. 带环链表 linked list cycle

    1 [抄题]: 给定一个链表,判断它是否有环. [思维问题]: 反而不知道没有环怎么写了:快指针fast(奇数个元素)或fast.next(偶数个元素) == null [一句话思路]: 快指针走2步 ...

  9. Lintcode 102.带环链表

    ------------------------ 只要设置两个指针,称为快慢指针,当链表没有环的时候快指针会走到null,当链表有环的时候快指针早晚会追上慢指针的. AC代码: /** * Defin ...

随机推荐

  1. Python3 tkinter基础 Listbox Button 点击按钮删除选中的单个元素

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  2. shell编程(三)之条件判断(if语句)

    练习:写一个脚本判断当前系统上是否有用户的默认shell为bash: 如果有,就显示有多少个这类用户:否则,就显示没有这类用户: #!/bin/bash # grep '\<bash$' /et ...

  3. word2010使用记录

    安装时提示: installer无法更新被保护的一个或多个文件, 解决方法是: 将三个dll文件,放在 c:\program files\common files\ms shared\web serv ...

  4. P2272 [ZJOI2007]最大半连通子图

    思路 tarjan的题目 注意是要选出一个点集而不是边集 第一问就是缩点之后最长链,第二问就是有多少个最长链,注意缩点后连边要去重(不然一个链的方案可能会被统计多次) 代码 #include < ...

  5. (转)awesome-text-summarization

    awesome-text-summarization 2018-07-19 10:45:13 A curated list of resources dedicated to text summari ...

  6. Vue.extend构造器和$mount实例构造组件后可以用$destroy()进行卸载,$forceUpdate()进行更新,$nextTick()数据修改

    html <div id="app"> </div> <p><button onclick="destroy()"&g ...

  7. The more... the more句型

    百度文库:https://wenku.baidu.com/view/a7f1067f59fb770bf78a6529647d27284a73374b.html the more ... , the m ...

  8. 【Hadoop 分布式部署 一 :分布式部署准备虚拟机 】

    一.将IP配置为静态 按照 下面的操作将IP配置为静态IP  这个静态的IP地址 是你自己设置的,只要符合虚拟机的IP段就可以.最后点击 Apply  需要root密码 将网络断开 (在网络图标左键  ...

  9. JQuery---高级类选择器

    1.ContentFilters 1.1 语法:$('div:contains(edu)').css('backgroundColor','yellow'); 只看div 本身是否包含内容 1.2 语 ...

  10. Twitter开发2

    There are different API families The standard (free) Twitter APIs consist of REST APIs and Streaming ...