LeetCode 141题 环形链表 (TS实现)

744 阅读2分钟

题目描述:

给你一个链表的头节点 head ,判断链表中是否有环。

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

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

写法一:借助map映射表

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function hasCycle(head: ListNode | null): boolean {
    let map = new Map()
    while(head){
      if(map.has(head)){
        return true
      }else{
        map.set(head,head)
      }
      head = head.next
    }
    return false
};

思路讲解:

核心:创建一个映射表,用来存储遍历的节点值

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

写法二:双指针方法

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function hasCycle(head: ListNode | null): boolean {
    let slow = head
    let fast = head
    
    while(fast && fast.next){
      fast = fast.next.next
      slow = slow.next
      if(fast === slow){
        return true
      }
    }
  
    return false
};

思路讲解:

核心: slow (慢指针每次跑一个节点) fast (快指针每次跑两个节点) 如果快指针在某一刻能等于慢指针(套了一圈)就证明有环,否则为无环

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