题目描述
Given a linked list, determine if it has a cycle in it.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Follow up:
Can you solve it using O(1) (i.e. constant) memory?
判断一个线性链表里是否有环,要求空间复杂度为O(1)
输入:该线性链表、链表尾部元素 连接的元素的下标(若没有环,则为-1)
输出:是否存在环
解题思路
两种思路:
-
HashSet——这个思路比较好想,逻辑比较简单
(1)先创建一个HashSet来存放head里的元素(HashSet不允许重复,元素无序)
(2)逐个遍历Linked List里的元素:若HashSet里不含有当前元素,就加入到HashSet里; 若HashSet里含有该元素了,说明 当前遍历到的元素是尾部元素连接的元素,也就说明存在环。
(3)若一直遍历到最后都没有元素在HashSet里已经存在过,说明无环
-
双指针—— 这个就非常巧妙了,也比较难想
(1)定义两个ListNode类型变量:slow、fast
(2)两个变量同时在Linked List里前进:slow跑得慢,一次只前进一步;fast跑得快,一次前进两步。
(3)如果有环,slow和fast必定会相遇。
实现代码
根据上述思路可得Java代码:.
思路1:hashSet
public boolean hasCycle(ListNode head) {
Set<ListNode> s = new HashSet<>();
while (head != null) {
if (s.contains(head)) { //若HashSet里已经存在当前遍历到的元素,说明有环
return true;
} else {
s.add(head); //若没有就加进去
}
head = head.next;
}
return false; //遍历结束了都没遇到已存在的结点,说明没环
}
思路2:双指针
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) { //先进行异常情形判断
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true; //slow 和fast相遇,说明有环
}