当前位置: 首页 > article >正文

数据结构与算法之链表: Leetcode 141. 环形链表 (Typescript版)

环形链表

  • https://leetcode.cn/problems/linked-list-cycle/

描述

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

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

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

示例 1

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示

  • 链表中节点的数目范围是 [0, 1 0 4 10^4 104]
  • - 1 0 5 10^5 105 <= Node.val <= 1 0 5 10^5 105
  • pos 为 -1 或者链表中的一个 有效索引

算法实现

1 )方案 1

/**
 * 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 p1 = head; // 单位1的速度指针
    let p2 = head; // 单位2的速度指针
    // while循环如果是环,则条件会一直为真,最终一定会相逢,即走到if中
    // while循环中如果走到了尽头,则会跳过while, 直接 return false
    while(p1 && p2?.next) {
        p1 = p1.next;
        p2 = p2.next.next;
        // 指针重逢意味着相逢,相逢意味着闭环
        if(p1 === p2) {
            return true;
        }
    }
    return false;
};
  • 这里需要注意的是,题目示例中给定 pos, 但并不是作为算法的输入参数
  • 这一点是比较迷惑的一点,如果示例中没有相关参数,则不能参与运算
  • 解题思路
    • 两个人在圆形操场上的起点同时起跑,速度快的人一定会超过速度慢的人一圈或多圈
    • 用一快一慢两个指针遍历链表,如果指针能够相逢,那么链表就有环
    • 慢指针,一次走一步;快指针,每次走两步
  • 解题步骤
    • 用一快一慢两个指针遍历链表,如果指针能够相逢,就返回true
    • 遍历结束后,还没有相逢就返回false

2 )方案 2

/**
 * 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 {
    while (head?.next) {
        const node = head.next // 临时存储当前节点的下一个节点
        if (node === head) return true // 当前节点的下一个节点是自己,检测到闭环
        head.next = head // 将当前节点赋值给当前节点的下一个节点
        head = node // 将当前节点的下一个节点赋值给当前节点
    }
    return false
};
  • 上述是官方示例,思路是基于一个点的移动,来判断是否可以找到自己
  • 找到自己,则闭环,找不到或者没有后继,则不是闭环

3 )方案 3

/**
 * 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 cursor = head // 初始化游标,赋值为头部节点
    const map = new Map() // 初始化Map存储结构
    while (cursor) {
        if (map.has(cursor)) return true // 检测到游标已经存在,则闭环
        map.set(cursor, true) // 存储更新游标
        cursor = cursor.next // 移动游标
    }
    return false
};
  • 以上也是官方提供的示例程序
  • 利用map存储的唯一性,来检测是否是闭环
  • 这个方法效率非常好

http://www.kler.cn/news/17010.html

相关文章:

  • 谷粒商城二十四Sentinel限流熔断降级
  • 用于scATAC-seq有监督分类的Cellcano
  • 【LeetCode刷题记录】数组专题
  • Python小姿势 - Python面向对象
  • 《基于深度学习模型的非接触式面部视频记录技术用于心房颤动的检测》阅读笔记
  • 「Codeforces」B. Avoid Local Maximums
  • Redis之五大基本的数据类型:字符串String 散列hashes 列表 lists 集合sets 有序集合sorted sets 基础命令讲解
  • 学生台灯什么牌子好对眼睛好?专业护眼灯的学生台灯分享
  • 【AI工具】bing chat 使用--三种模式+撰写功能
  • gradle Task 详解
  • 什么是Filter?
  • 工具及方法 - 安装播放器pot player
  • 大二一个学期学这么点内容,没有概念,只有实操
  • TCP的三次握手和四次挥手
  • 冲浪杂记——
  • Apollo 7.0——percception:rader源码剖析
  • win11本地安全机构保护已关闭怎么办?如何修复windows11本地安全机构保护已关闭?
  • ubuntu: ubuntu22.04安装redis数据库,并设置开机自启动
  • Redis底层设计与源码分析(一)__底层数据结构逻辑分析
  • 低代码,一招制敌,解决职场人的的办公难题
  • 【热门框架】Maven中聚合,继承指的是什么?有什么作用?
  • 刚转岗做项目经理,无从下手,怎么办?
  • 【硬件】嵌入式电子设计基础之分析电路
  • 视频转gif如何做?三步教你视频转gif制作
  • ClickHouse的资料
  • JetBrains 公布 WebStorm 2023.2 路线图
  • 软件测试技术(四)白盒测试
  • 五面阿里Java岗,从小公司到阿里的面经总结
  • Docker file镜像
  • C/C++内存泄露检查利器—valgrind