思路: 当两个指针相遇,证明链表有环的时候,让两个指针从相遇点继续循环前进,并统计前进的循环次数,直到两个指针第2次相遇,此时,统计出来的前进次数就是环数。
思考一下:假设两指针分为为p1,p2,则指针p2每次比p1多走一步,两者的速度差为1步,当两个指针再次相遇,p2比p1多走了1圈,因此 环长 = 每一次速度差 X 前进次数 = 前进次数
一下代码有两种,分别是本人自己解法和网上的解法:
/**
* 判断环的长度: 自己解法
*
* @param node
* @return
*/
public static Integer cycleLength(Node node) {
// 相遇次数
final Integer FIRST_MEET = 1;
final Integer SECOND_MEET = 2;
// 1 设置快慢指针
Node slower = node;
Node quick = node;
// 相遇次数
Integer meetCount = 0;
// 环的长度
Integer length = 0;
// 2 当两者相遇时,设置计数器,当两者再次相遇,再计数器的长度则为环的长度
while (quick != null && quick.next != null) {
slower = slower.next;
quick = quick.next.next;
if (slower == quick) {
// 相遇的次数
meetCount++;
}
if (meetCount.equals(FIRST_MEET)) {
// 第一次相遇,则继续执行,开始计算环的长度
length++;
}
if (meetCount.equals(SECOND_MEET)) {
// 第二次相遇,则跳出循环
break;
}
}
return length;
}
/**
* 判断环的长度:网上版本
* @param node
* @return
*/
public static Integer cycleLength1(Node node) {
// 1 设置快慢指针
// 2 当两者相遇时,设置计数器,当两者再次相遇,再计数器的长度则为环的长度
Node slower = node;
Node quick = node;
Integer meetCount = 0;
while (quick != null && quick.next != null) {
slower = slower.next;
quick = quick.next.next;
if (slower == quick) {
// 计算环的长度
// 环的长度
Integer length = 0;
while (quick != null && quick.next != null) {
slower = slower.next;
quick = quick.next.next;
length++;
if (slower == quick) {
return length;
}
}
}
}
return 0;
}
public static void main(String[] args) {
Node node = new Node(5);
Node node1 = new Node(3);
Node node2 = new Node(7);
Node node3 = new Node(2);
Node node4 = new Node(6);
Node node5 = new Node(8);
Node node6 = new Node(1);
node.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = node3;
// 环的长度
Integer length = cycleLength1(node);
System.out.println("该链表环的长度为:" + length);
}