定义一个链表。如:
1->2->3->4->5->6->7->8->9->10
算法思路:
理解一:从头开始遍历链表,当遍历到链表最后看指针是否存在指向前面的元素或者,如果存在这表示有环,返回true,如果指针指向空这表示没有环,返回false
理解二:如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达该节点,则链表中存在环
如果链表中存在环,则返回 true 。 否则,返回 false 。
算法代码实现
实现一:哈希表、Set去重方式
package com.hx;
import java.util.HashSet;
import java.util.Set;
public class LinkCycle {
static class LinkNode{
private int val;
private LinkNode next;
public LinkNode(int val, LinkNode next) {
this.val = val;
this.next = next;
}
}
public static void main(String[] args) {
LinkNode node10 = new LinkNode(10,null);
LinkNode node9 = new LinkNode(9,node10);
LinkNode node8 = new LinkNode(8,node9);
LinkNode node7 = new LinkNode(7,node8);
LinkNode node6 = new LinkNode(6,node7);
LinkNode node5 = new LinkNode(5,node6);
LinkNode node4 = new LinkNode(4,node5);
LinkNode node3 = new LinkNode(3,node4);
LinkNode node2 = new LinkNode(2,node3);
LinkNode node1 = new LinkNode(1,node2);
node10.next = node5;
System.out.println(isCycle(node1));
}
/**
* 使用set特性查找判断链表中是否存在环
* @param head
* @return
*/
public static boolean isCycle(LinkNode head) {
Set<LinkNode> linkSet = new HashSet<LinkNode>(); //利用set的不可重复读特性
while (head != null) { //如果set可以添加节点表示不存在环,如果不可以添加表示有环
if(!linkSet.add(head)) {
return true;
}
head = head.next;
}
return false;
}
}
执行结果
实现二: 双指针
实现思路:定义两个指针,一个快指针quick一个慢指针slow。快指针遍历快。如果快慢指针在链表中某个节点重回,或者两个指针指向同一个节点,则表示有环,返回true。反之返回false
实现代码
package com.hx;
import java.util.HashSet;
import java.util.Set;
public class LinkCycle {
static class LinkNode{
private int val;
private LinkNode next;
public LinkNode(int val, LinkNode next) {
this.val = val;
this.next = next;
}
}
public static void main(String[] args) {
LinkNode node10 = new LinkNode(10,null);
LinkNode node9 = new LinkNode(9,node10);
LinkNode node8 = new LinkNode(8,node9);
LinkNode node7 = new LinkNode(7,node8);
LinkNode node6 = new LinkNode(6,node7);
LinkNode node5 = new LinkNode(5,node6);
LinkNode node4 = new LinkNode(4,node5);
LinkNode node3 = new LinkNode(3,node4);
LinkNode node2 = new LinkNode(2,node3);
LinkNode node1 = new LinkNode(1,node2);
node10.next = node5;//创建环关系
System.out.println(isCycleByNext(node1));
}
/**
* 双指针实现验证时候存在环的算法
* @param head
* @return
*/
public static boolean isCycleByNext(LinkNode head) {
if(head == null) {
return false;
}
LinkNode slow = head;
LinkNode quick = head.next;
while (slow != quick) { //指针不相同的时候进行链表移动
if(quick == null || quick.next == null) { //说明链表移动完成,不存在环
return false;
}
slow = slow.next; //慢指针指向下一个节点
quick = quick.next.next;//快指针指向下一个节点
}
return true;
}
}
执行结果