题目描述:

给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
image.png

写法一:借助map映射表

  1. /**
  2. * Definition for singly-linked list.
  3. * class ListNode {
  4. * val: number
  5. * next: ListNode | null
  6. * constructor(val?: number, next?: ListNode | null) {
  7. * this.val = (val===undefined ? 0 : val)
  8. * this.next = (next===undefined ? null : next)
  9. * }
  10. * }
  11. */
  12. function hasCycle(head: ListNode | null): boolean {
  13. let map = new Map()
  14. while(head){
  15. if(map.has(head)){
  16. return true
  17. }else{
  18. map.set(head,head)
  19. }
  20. head = head.next
  21. }
  22. return false
  23. };

思路讲解:

核心:创建一个映射表,用来存储遍历的节点值
思路:首先我们通过new Map()创建一个hash映射表,然后遍历循环此链表,如果映射表没有当前遍历的节点,则把当前节点存储到映射表里。如果映射表存在当前节点,则证明此节点走了两次,此链表存在环。如果遍历到最后都未出现当前节点与映射表里节点相同情况,则证明此链表不存在环。

写法二:双指针方法

  1. /**
  2. * Definition for singly-linked list.
  3. * class ListNode {
  4. * val: number
  5. * next: ListNode | null
  6. * constructor(val?: number, next?: ListNode | null) {
  7. * this.val = (val===undefined ? 0 : val)
  8. * this.next = (next===undefined ? null : next)
  9. * }
  10. * }
  11. */
  12. function hasCycle(head: ListNode | null): boolean {
  13. let slow = head
  14. let fast = head
  15. while(fast && fast.next){
  16. fast = fast.next.next
  17. slow = slow.next
  18. if(fast === slow){
  19. return true
  20. }
  21. }
  22. return false
  23. };

思路讲解:

核心:slow(慢指针每次跑一个节点) fast(快指针每次跑两个节点) 如果快指针在某一刻能等于慢指针(套了一圈)就证明有环,否则为无环
思路:首先我们定义一个慢指针slow和一个快指针fast,让他们都等于第一个节点head。我们每次让fast走两个节点(即fast=fast.next.next),每次让slow走一个节点(即slow=slow.next)。由于fast要跑的快一点,所以我们循环的条件为如果fast存在,并且fast的下一个节点也存在我们才会继续执行。 在循环执行的过程中如果某一个时刻fast === slow 及二者重合了,就证明链表存在环。 如果知道最后也没出现fast === slow,则此链表就没有环。