给定一个链表,判断链表中是否有环。存在环返回 true ,否则返回 false
分析:
该题可以理解为检测链表的某节点能否二次到达(重复访问)的问题。
需要一个容器记录已经访问过的节点 每次访问到新的节点,都与容器中的记录进行匹配,若相同则存在环 若匹配之后没有相同节点,则存入容器,继续访问新的节点 直到访问节点的next指针返回null,或者当前节点与容器的某个记录相同,操作结束。
- 实现简单,时间复杂度为:O(n^2)
- 遍历整个链表:O(n)
- 每次遍历节点,再遍历数组进行匹配:O(n)
换个思路:
该题可以理解为“追击相遇”问题,如果存在环,跑得快的一定能追上跑得慢的。
比如:一快一慢两个运动员,如果在直道赛跑,不存在追击相遇问题;如果是在环道赛跑,快的绕了一圈肯定可以追上慢的。
题解:
- 定义快慢两个指针: slow=head; fast=head.next;
- 遍历链表: 快指针步长为2:fast=fast.next.next; 慢指针步长为1:slow=slow.next;
- 当且仅当快慢指针重合(slow==fast),有环,返回true
- 快指针为null,或其next指向null,没有环,返回false,操作结束
public class RingList {
public static boolean isRing(Node head){
if (head == null){
return false;
}
Node slow = head;
Node fast = head.next;
while (fast != null && fast.next != null){
if (slow == fast){
return true;
}
fast = fast.next.next;
slow = slow.next;
}
return false;
}
}
时间复杂度为:O(n)