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?
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
方法一:利用 HashMap
利用 HashMap 中键唯一的特点,将 ListNode 作为 HashMap 的键,这样可以快速查找 HashMap 中是否已经存在这个键。而对于有环的链表,必定会出现重复的键;而对于没有环的链表,总有 head.next == null 为 true 的情况
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null){
return false;
}
HashMap<ListNode, Integer> a = new HashMap<>();
while(head.next != null){
if(a.containsKey(head)){
return true;
}
else{
a.put(head, head.val);
head = head.next;
}
}
return false;
}
复杂度分析:
时间复杂度:O(n).
空间复杂度:O(n).
与方法一同样的思想,只是语言更简化。
public boolean hasCycle2(ListNode head) {
Set<ListNode> nodesSeen = new HashSet<>();
while (head != null) {
if (nodesSeen.contains(head)) {
return true;
} else {
nodesSeen.add(head);
}
head = head.next;
}
return false;
}
方法二:设置两个指针
思路: 想象两个人以不同的速度沿相同的轨迹跑,如果轨迹是个环,那么两个人总会相遇。
这里用这种思想,用两个指针,沿着链表以不同的速度移动,当两个指针指向的对象为同一对象时,说明链表中存在环,则返回 true;
当较快的指针指向 null 时,说明链表中没有环,则返回 false。
public boolean hasCycle3(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;
}
复杂度分析:
时间复杂度:O(n)
空间复杂度:O(1)