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步就会相遇。

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

相关推荐
_阿南_7 小时前
项目中新增给AI制定的代码规范
前端·程序员
名字还没想好☜8 小时前
React 实现暗黑模式切换:localStorage 持久化、SSR 首屏闪烁与跟随系统主题
前端·javascript·react.js·ecmascript·react·next.js
find1star8 小时前
LeetCode 141:环形链表
java·算法·leetcode·链表
迅翼SwiftWing9 小时前
编队系列(总)|固定翼编队如何实现稳定飞行?通信架构、协同算法与工程约束深度解析
算法·架构
LB21129 小时前
力扣160 21 86
算法·leetcode·职场和发展
console.log('npc')9 小时前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
小智老师PMP10 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
HugoStudio_SWAN10 小时前
洛谷 B4450 / B3867 / B3923 智慧购物、储蓄与做题——从程序到生活
c++·学习·程序人生·算法·生活
爱学堂IT分享10 小时前
Cesium可视化系统实战课程-Cesium教程学习
前端
a1879272183110 小时前
【算法】动态规划第二篇:双序列 DP 三课——继承、计步与断链
算法·leetcode·动态规划·dp·回溯·暴力·算法讲解