快慢指针算法

快慢指针

简介

快慢指针就是定义两根指针,移动的速度一快一慢,以此来制造出自己想要的差值。这个差值可以让我们找到链表上相应的节点。

  • 求一个链表的中间值,我们将快指针每次走两步,慢指针每次走一步。当快指针到达末尾,慢指针就是中间值。
  • 删除链表的倒数第 N 个值,我们将快指针每次走 1 步,慢指针每次走 1 步但是比快指针慢 N 步。当快指针到达末尾,慢指针就是需要删除的点。
  • 判断链表是否是循环链表,我们将快指针每次走两步,慢指针每次走一步。当快指针和慢指针相遇就表示有环,否则没有。类似我们操场上跑步,如果是一个环,那么跑的快的人肯定会和跑的慢的人再次相遇。

示例

141. 环形链表

var hasCycle = function (head) {
  let slow = head;
  let fast = head;
  while (fast) {
    if (!fast.next) return false;
    fast = fast.next.next;
    slow = slow.next;
    if (fast === slow) return true;
  }
  return false;
};

进阶

142. 环形链表 II

  • 首先根据上一个方法先确定有没有环
  • 其次我们再找到入环节点
               D    E

A    B    C             F

               H    G

  • 假设我们在 D 点相遇
  • L 表示环的长度
  • Lf 快指针走的路程
  • Ls 慢指针走的路程
  • S1 = ABC
  • S2 = CD
  • S3 = DEFGHC
  • 相遇时候慢指针跑了 m 圈,Ls = S1 + m * L + S2
  • 相遇时候快指针跑了 n 圈,Lf = s1 + n * L + S2
  • 2 * Ls = Lf
  • S1 + S2 = (n - 2 * m) * L
  • 我们用 x 表示 (n - 2 * m), x >= 1
  • S1 + S2 = x * L
  • 我们用 y 表示 x - 1, y >= 0
  • y * L + (L - S2) = S1
  • S2 + S3 = L
  • S1 = S3 + y * L
  • 因此我们再使用一个慢指针,两个慢指针分别从 A D 两点出发,最后肯定会在 C 点相遇
    • 假设走了 y * L 距离,从 A 点出发的指针还剩 S3 距离到达 C 点
    • 而另一个指针肯定还在 D 点(转了 y 圈),这个时候他也剩 S3 距离到达 C 点
var detectCycle = function (head) {
  let slow = head;
  let fast = head;
  let start = head;
  while (fast) {
    if (!fast.next) return null;
    fast = fast.next.next;
    slow = slow.next;
    if (fast === slow) {
      while (start != slow) {
        slow = slow.next;
        start = start.next;
      }
      return slow;
    }
  }
  return null;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值