1.思路
思路一:从头节点开始,依次遍历节点中的每一个节点。每次遍历一个新的节点的时候,从头开始重新遍历之前的节点,用新的节点判断是否和之前的节点是否相同,如果相同,则说明该链表有环;如果不相等,继续遍历,直到最后一个节点,若不想等,则说明无环。实现的时间负责复杂度为O(n*n),空间复杂度为O(1)
思路二:创建一个以节点ID为Key的HashSet集合,用来存储遍历过的节点的值,然后从头节点开始,一次遍历链表中的每一个节点的值,每遍历一个节点,就以新节点和存储在HashSet结合中的节点作比较,如果HashSet中有和新节点相同的ID,则说明该链表有环,反之没有。时间复杂度为O(n),空间复杂度为O(n)
思路三:创建两个指针(p1、p2),让其都指向链表的第一个节点,p1每次向后移动一个位置,p2每次向后移动两个位置,每次移动之后判断两个指针指向的节点的值是否相同,若相同,则说明链表有环;反之说明链表无环。代码如下:
2.代码实现
package com.linklist;
public class CycleNode {
/**
* 静态内部类
* @author YangYong
*
*/
private static class Node{
//值
int data;
//指针,用于指向下一个节点,最后一个节点指向null
Node next;
//构造方法
Node(int data){
this.data = data;
}
}
/**
* 判断一个链表是否有环
* @param head
* @return
*/
public static boolean isCycle(Node head) {
//让两个指针同时指向头节点
Node p1 = head;
Node p2 = head;
while(p2 != null && p2.next != null) {
//p1节点每次移动一个节点的位置
p1 = p1.next;
//p2节点每次移动两个指针的位置
p2 = p2.next.next;
//每移动一次判断他们两个指向的节点是否相等
if(p1 == p2) {
return true;
}
}
return false;
}
/*
* 测试方法
*/
public static void main(String[] args) {
Node node1 = new Node(5);
Node node2 = new Node(3);
Node node3 = new Node(7);
Node node4 = new Node(2);
Node node5 = new Node(6);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node2;
System.out.println(isCycle(node1));
}
}