leetcode(js) 141. 环形链表

  1. 环形链表
    给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例 1:

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

示例 2:

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

示例 3:

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

在这里插入图片描述

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

解题思路:这里学习了floyd判圈算法,也称龟兔赛跑算法

思路就是设置两个指针,一个跑的快,一个跑的慢,都从起点开始,跑的快的每次两步,跑的慢的每次一步,如果有环他们迟早会相遇的。

这个思想也能用来求出环的长度
当相遇了之后,继续让跑得慢的走,就是那个每次一步的继续走,等到再次相遇,走的步数就是环的长度。

上面两种在网上资料中的解释:
判断是否存在环路:

如果有限状态机、迭代函数或者链表存在环,那么一定存在一个起点可以到达某个环的某处(这个起点也可以在某个环上)。
初始状态下,假设已知某个起点节点为节点S。现设两个指针t和h,将它们均指向S。接着,同时让t和h往前推进,但是二者的速度不同:t每前进1步,h前进2步。只要二者都可以前进而且没有相遇,就如此保持二者的推进。当h无法前进,即到达某个没有后继的节点时,就可以确定从S出发不会遇到环。反之当t与h再次相遇时,就可以确定从S出发一定会进入某个环,设其为环C。如果确定了存在某个环,就可以求此环的起点与长度。
求解环路的长度:
上述算法刚判断出存在环C时,显然t和h位于同一节点,设其为节点M。显然,仅需令h不动,而t不断推进,最终又会返回节点M,统计这一次t推进的步数,显然这就是环C的长度。

还有个更强的:能退着求出这个环的起点
网上资料中的解释
为了求出环C的起点,只要令h仍均位于节点M,而令t返回起点节点S,此时h与t之间距为环C长度的整数倍。随后,同时让t和h往前推进,且保持二者的速度相同:t每前进1步,h前进1步。持续该过程直至t与h再一次相遇,设此次相遇时位于同一节点P,则节点P即为从节点S出发所到达的环C的第一个节点,即环C的一个起点。
简单翻译:就是当快慢指针相遇的时候,他们是可能相遇在环上的某个点,而不是这个环的起点,所以这样怎么算哪个是点是起点呢?可以多画图测试一下理解一下,这个时候让一个指针回到整个遍历起始的节点,这两个指针之间必然是环长度的整数倍,然后同时走一步进行推进,能在第一个节点相遇。

在这里插入图片描述
可以参考这个图多画画试试或者自行想象

解题思路2:也可以考虑到JSON.stringfy的不能序列化含有循环引用的结构
通常,我们会用JSON.stringify把Javascript对象序列化成JSON格式,这在大多数情况下是够用的。但是,当你要转换的对象里存在循环引用时,就会报错了
在这里插入图片描述
所以思路就是直接用JSON.stringfy把这个指针对象转换成字符串,如果成功运行了就是没有环,如果运行出错,就是有环,这个有没有成功运行的判断,可以用到try+catch

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function(head) {
    let fast = head;
    let slow = head;
    while(fast&&slow&&fast.next){
        fast = fast.next.next;
        slow = slow.next;
        if(slow == fast)return true

    }
    return false;
};
var hasCycle = function(head) {
    try{
        JSON.stringify(head);
        return false;
    }
    catch(err){
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值