LeetCode 141. Linked List Cycle
Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
题意:给定一个链表,判断链表中是否存在环路。
注:不能使用额外的空间
思路:百度的解决方法。设置一个快指针,一个慢指针。存在环路的链表相当于钟表,快指针和慢指针相当于分针和时针,在钟表中,分针比时针快,但两者总会有重叠的时候。在链表中道理相同,如果链表存在环路,则两个快慢指针总会重叠(即指向同一个结点)。
参考:https://www.cnblogs.com/grandyang/p/4137187.html
public boolean hasCycle(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; if (slow == fast) return true; } return false; }
LeetCode提供的解决方法:
1. 原理相同,只是与上述方法中的循环结束条件不同
public boolean hasCycleTwo(ListNode head) { if (head == null || head.next == null) return false; ListNode slow = head; ListNode fast = head.next; // 如果slow和fast第一次都指向head,则有slow==fast,因此在初次定义的时候fast要指向head.next,因此要先判断head.next不为空 while (slow != fast) { if (fast == null || fast.next == null) return false; slow = slow.next; fast = fast.next.next; } return true; }
2. 利用集合。为了检测链表中是否存在环路,从head开始逐个加入集合,检查该结点是否在之前被访问过。但该方法需占用额外空间
注:也可以使用线性表,但在测试一个元素是否在集合或线性表方面,集合比线性表更加高效。
public boolean hasCycle(ListNode head) { Set<ListNode> set = new HashSet<>(); ListNode cur = head; while (cur != null) { if (!set.contains(cur)) set.add(cur); else return true; cur = cur.next; } return false; }