这是我参与更文挑战的第6天,活动详情查看: 更文挑战
这题是快慢指针的应用,如果没有这方面的思想,或者之前结果类似的题,很难想到,一般容易想到的是使用set判断。
方法一:Set集合
public boolean hasCycle(ListNode head) {
HashSet<ListNode> set = new HashSet<>();
while (head != null) {
//如果set里面已经存在,那么不会添加成功
if (!set.add(head)) {
return true;
}
head = head.next;
}
//没有环
return false;
}
方法很简单,利用set不能存放重复数据实现。
复杂度分析
-
时间复杂度:,最坏情况需要遍历每个节点一次。
-
空间复杂度:,最坏情况需要将每个节点插入到
set中一次。
方法二:快慢指针
快慢指针的意思是,快指针隔着几个元素遍历链表,慢指针是一个一个元素的遍历,当存在环,快指针会在环里遍历n圈,直到慢指针进入圈里相遇,如果没有环,那么它们将用于不会相遇。
public boolean hasCycle(ListNode head) {
if (head == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
if (fast == null) {
return false;
}
while (fast.next != null && fast.next.next != null) {
if (fast == slow) {
return true;
}
// 慢指针移动一个
slow =slow.next;
//快指针移动两个
fast = fast.next.next;
}
//没有环
return false;
}
复杂度分析
-
时间复杂度:,没环的情况,遍历一次链表长度;有环,快慢指针相遇,最多是慢指针移动
n次。 -
空间复杂度:,常数空间。