问题描述:
判断链表是否有环,如若有环则返回其进入环的第一个节点。
算法一:
创建一个哈希表,遍历该链表过程中将判断该节点是否已存在于哈希表,如不存在则将其插入哈希表,存在则证明链表有环,并且该元素即为进入环的第一个节点;链表遍历过程中出现null则证明该链表无环。
实现代码如下:
public static Node<Integer> selution(Node<Integer> head){
Node<Integer> loopHead = null;
Set<Node<Integer>> set = new HashSet<>();
for (Node<Integer> pointer = head; pointer != null; pointer = pointer.next) {
if (set.contains(pointer)) {
loopHead = pointer;
break;
}else {
set.add(pointer);
}
}
return loopHead;
}
其时间复杂度为O(N),额外空间复杂度为O(N)。
算法二:
/*
* 定义快慢两个指针,快指针一次走两步,慢指针一次走一步,若他两能相遇则证明有环
* 相遇之后,让快指针指向头结点,此时快指针(一次一步)与慢指针同时移动,相遇位置即为环头
*/
代码实现如下:
public static Node<Integer> selution1(Node<Integer> head){
Node<Integer> loopHead = null;
Node<Integer> fastPoint = head.next.next;
Node<Integer> slowPoint = head.next;
boolean loop = false;
while (fastPoint != null) {
if (fastPoint == slowPoint) {
loop = true;
break;
}
if (fastPoint.next != null && fastPoint.next.next != null) {
slowPoint = slowPoint.next;
fastPoint = fastPoint.next.next;
}else {
break;
}
}
if (loop) {
fastPoint = head;
while(fastPoint != slowPoint) {
fastPoint = fastPoint.next;
slowPoint = slowPoint.next;
}
loopHead = slowPoint;
}
return loopHead;
}
其时间复杂度为O(N),额外空间复杂度O(1)。
算法证明我发现一写的还挺不错的。