141. 环形链表

image.png
image.png

快慢指针版本一

  1. public class Solution {
  2. // 使用快慢指针法,快指针每次走两步,慢指针每次走一步,如果链表有环,则快慢指针一定会相遇
  3. public boolean hasCycle(ListNode head) {
  4. if (head == null || head.next == null) return false;
  5. // 快指针
  6. ListNode fast = head.next;
  7. // 慢指针
  8. ListNode slow = head;
  9. while (fast != slow) {
  10. // 如果为空,说明跑完了,没有环,返回 false
  11. if (fast == null || fast.next == null) return false;
  12. fast = fast.next.next;
  13. slow = slow.next;
  14. }
  15. return true;
  16. }
  17. }

快慢指针版本二

  1. public class Solution {
  2. public boolean hasCycle(ListNode head) {
  3. if (head == null || head.next == null) return false;
  4. // 慢指针
  5. ListNode fast = head.next;
  6. // 快指针
  7. ListNode slow = head;
  8. // 如果快指针与快指针的下个节点都不为空,则继续遍历
  9. // 为什么判断快指针?因为快指针先到达终点,如果链表没有环,到终点时为空
  10. while (fast != null && fast.next != null) {
  11. // 如果快指针与慢指针相等,说明相遇了,返回 true
  12. if (fast == slow) return true;
  13. slow = slow.next;
  14. fast = fast.next.next;
  15. }
  16. return false;
  17. }
  18. }

使用 set 存放节点

  1. public class Solution {
  2. // 使用一个 set 记录遍历过的节点
  3. public boolean hasCycle(ListNode head) {
  4. if (head == null) return false;
  5. Set<ListNode> set = new HashSet<>();
  6. while (head != null) {
  7. // 如果节点在 set 中,说明有环
  8. if (set.contains(head)) return true;
  9. set.add(head);
  10. head = head.next;
  11. }
  12. return false;
  13. }
  14. }