【剑指算法NO.02】142.环形链表II

前端印记

共 1725字,需浏览 4分钟

 ·

2021-11-24 10:24



本篇是在141.环形链表的基础上进行的分析和运算。没有看之前文章的推荐先看上篇再看本篇。

入环口判断

上篇开头我们提到过,需要利用快慢指针在环中的移动规律来得到环的入口点。

现在我们紧接着上篇的思路,再来探讨一下,怎么根据快慢指针找出入环口结点。

按照之前的推论,当快慢指针在相遇点汇合时,相遇点距离入环口的距离就是L-(L-A),也就是距离为A

冥冥中注定,我们可以从图中看到,链表起点(head 头节点)到达入环口的距离也是A

现在我们让慢指针站住不动、快指针回到头节点。之后再让 快、慢指针同时开始运动、且保持步数都为1快指针以一次 1 步的速度,从头节点入环口运动;慢指针也以一次 1 步的速度,从相遇点入环口运动;因为快、慢指针的距离相同,所以二者会在入环口再次相遇:在他们相遇时,我们就能得到入环口对应的结点是谁了。

上代码

我们第一遍循环的时候,先找到相遇点。并在第一次的相遇点处让快指针回到开头、并把速度降低到和慢指针一样。接下来第二遍循环,我们只需要找到二者相等的位置结点并返回即可。

/**
 * 快慢指针
 */

var detectCycle = function(head{
  // 先判断是否具备形成环的条件(结点数量不能小于两个)
  if(head === null || head.next === nullreturn null
  // 准备好快慢指针
  let slow = head
  let fast = head
  // 第一遍循环,找相遇点
  while(fast && fast.next) {
    // 快指针一次走2步,慢指针一次走1步
    slow = slow.next
    fast = fast.next.next
    // 相遇以后结束循环,并让快指针回到起始节点
    if(slow === fast) {
      // 在相遇点相遇了,就要fast赶回起点
      fast = head
      break
    }
  }

  // 没相遇且结束了循环,就说明没有环,直接return null
  if(fast !== head) return null 

  // 否则说明有环,第二次遍历寻找入环口
  while(slow !== fast) {
    // fast和slow分别从起点及相遇点出发,每次走1步,直到相遇就是入环口。
    slow = slow.next
    fast = fast.next
  }
  // 最后返回入环口的结点(因为此时slow===fast,所以返回谁也行)
  return slow
};

对比哈希的缺点:如果链表长、环的长度比非环的长度小,则需要更多次的循环

同样的,这个题依旧可以使用哈希表的方式来求解:

/**
 * 哈希表
 * 缺点:空间复杂度。哈希就是空间换时间
 */

var detectCycle = function(head{
  let map = new Map()
  while(head) {
    if(map.has(head)) return head
    map.set(head, true)
    head = head.next
  }
  return null
};


Hi,读到这里的你~
我们有一群人(十来个吧)正在组队用JS刷 LeetCode 算法题,小队内有明确的打卡规则与惩罚制度,队员们也都每天积极的刷题打卡。如果你也想加入的话请与我联系,欢迎进来和我们一起成长。
刷题排行榜:http://123.56.222.177/
算法打卡地址:https://gitee.com/xingorg1/algorithmic-clock-out/issues


愿你历尽千帆,归来仍是少年。


让我们一起携手同走前端路!

长按下图识别二维码 关注公众号回复【加群】即可


浏览 32
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报