Leetcode刷题 41|142题

很多前端的同学对数据结构和算法这块没有太多的概念,很多leetcode的题目看不懂,有时候可能看了题解也不知道是什么意思。上一篇我们对链表的数据结构有了了解,下面根据题目来练习一下

141. 环形链表

题目

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

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

题解

这道题目最常见的解法就是快慢指针。我们经常把判断一个链表有环来比作是操场,因为操场肯定是一个环。假设有两个人在操场上跑圈,一个人跑的快一个人跑的慢。跑的快的人肯定会比跑的慢的人多跑一圈并追上跑的慢的人。 我们用图来表示一下。

slow表示跑的慢的人,fast表示跑的快的人,所以只要是在操场上跑(有环)fast就一定会比slow多跑一圈并追上他。回到我们的题目中,我们用一个慢指针,和一个快指针,慢指针每次都一步,快指针每次都两步,所以我们只需要判断快慢指针是否会相遇就可以判断这个链表是否有环了。

在链表中,每个节点只会知道它的下一个节点,所以一个节点或者没有节点是无法判断链表中是否有环的。所以我们首先需要对这个边界条件进行判断

js 复制代码
var hasCycle = function(head) {
    if (!head || !head.next) return false
};

如果这个链表没有环,那么fast永远都不会追上slow,直到fast指针最后会遇到null,说明链表没有环。否则fast会超过slow 一圈并与slow相遇,说明这个链表有环

js 复制代码
var hasCycle = function(head) {
    if (!head || !head.next) return false

    let fast = head, slow = head
    while (fast && fast.next) {
        fast = fast.next.next
        slow = slow.next
        if (fast === slow) {
              return true
        }
    }

  return false
};

142. 环形链表 II

题目

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

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

不允许修改 链表。

题解

我们简单的来概述一下这道题:如果链表有环,那么就返回这个环的起始位置。比如在实例1中,环的起始位置就是1。实例2中,环的起始位置就是0.

所以我们首先要根据上面一道题来判断链表是否有环。如果没有环则返回null

js 复制代码
var detectCycle = function (head) {
  if (!head) return null
  let slow = fast = head
  while (fast && fast.next) {
    fast = fast.next.next
    slow = slow.next
    if (fast === slow) {
      // 需要在这里面处理
    }
  }
  return null
};

当快慢指针相遇的时候,我们需要在此处理逻辑。

通过上面的图可以看到,快指针每次都两步,慢指针每次都一步,节点6快慢指针会相遇。我们通过观察可以发现一个现象,从相遇点节点6开始走两步,和从头节点开始走两步,刚好可以在环的连接点相遇。那么就可以找到答案了。我们先把代码实现一下,然后再来解释一下这种情况。

js 复制代码
var detectCycle = function (head) {
  if (!head) return null
  let slow = fast = head
  while (fast && fast.next) {
    fast = fast.next.next
    slow = slow.next
    if (fast === slow) {
      let cur = head
      while (cur !== slow) {
        cur = cur.next
        slow = slow.next
      }

      return cur
    }
  }
  return null
};

当快慢指针相遇的时候,让慢指针和头节点的指针一起走,只要他两相遇那么我们就找到了环的链接点。

下面我们来解释一下这种情况

从图中可以看到,如果slow走了x步,那么fast就走了2x,而fast比slow整整多了一圈,所以从相遇点到环起点是x-m, 从起点到环起点也是x-m,所以当fast和slow相遇的时候,我们只需要从头节点和相遇点同时出发,在x-m步就会相遇。

欢迎大家点赞评论,大家一起学习一起进步!!!

相关推荐
Jerry1 小时前
LeetCode 459. 重复的子字符串
算法
成都渲染101云渲染66662 小时前
如何在3ds Max中实现更快、更高质量的渲染
前端·javascript·人工智能
闲猫4 小时前
Spring AI 对接Deepseek ChatModel 聊天对话
java·前端·spring
海石4 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石4 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
自信的未来5 小时前
JSON 工具|Web Worker 工程化打包 + 语法自动修复 + 多语言代码生成实战
java·前端·json
全栈前端老曹6 小时前
【MongoDB】安全与权限管理 —— 用户认证、角色权限、SSL 加密
前端·javascript·数据库·安全·mongodb·nosql·ssl
Jerry6 小时前
LeetCode 151. 反转字符串中的单词
算法
zhangxingchao7 小时前
AI大模型核心八:从 Agent Skill、长文档 RAG 到知识库更新与训练策略
前端·人工智能·后端
zhangxingchao7 小时前
AI大模型核心七:从 Workflow、RAG、记忆治理到幂等性
前端·人工智能·后端