【路飞】-算法练习——环形链表

258 阅读3分钟

今天继续刷算法,本人其实已经很久没有刷过算法了,所以最近刷的题目还是比较简单的,题目也都是来源力扣,大家将就着看吧~

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

例1: circularlinkedlist.png

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

例2: circularlinkedlist_test2.png

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

例3: circularlinkedlist_test3.png

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

思路】:这个题目看得让人很迷惑,搞不懂那个pos有啥用。。。姑且就直接不管它,就按常规环形链表做,方法也比较简单,快慢追赶法,就像两个人操场跑步,一个速度是另一个两倍,当快的从后面追上慢的,那就表示有环了

【代码】:

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

/**
 * @param {ListNode} head
 * @return {boolean}
 */
var hasCycle = function(head) {
    if(!head) return false
    if(head && !head.next) return false

    let pre = head,next = head.next

    while(next && next.next !== null){
        pre = pre.next
        next = next.next.next

        if(pre === next) {
            return true
        }

    }
    return false
};

所以。。。那个pos到底有啥用?还是我题做错了?😑

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

例1: circularlinkedlist.png

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

例2: circularlinkedlist_test2.png

输入: head = [3,2,0,-4], pos = 1
输出: 返回索引为 1 的链表节点
解释: 链表中有一个环,其尾部连接到第二个节点。

例3: circularlinkedlist_test3.png

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

image.png

这跟上面那题有什么区别???

en...好像...是有那么一点点不一样,这个时不仅要找出环,还得找出第一次出现环的节点

思路】:完了,没思路了。。。

微信图片_20211207223918.png

让你来刷题,又不是来考试!!!

看一下前人的思路: image.png

总结说就是,先这样,再这样,然后再那样,最后快慢快两个指针第二次相遇的节点就是环的入口😏

【代码】:

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

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var detectCycle = function(head) {
    if(!head) return null
    if(head && !head.next) return null

    let slow = head.next, // 一次走一步
        fast = head.next.next // 一次走两步 

    while(fast){
        if(fast !== slow){
            if(!fast.next){
                return null // 没有环
            }
            slow = slow.next // 一次走一步
            fast = fast.next.next // 一次走两步 
        }else{
            let cur = head
            // 找第二次相遇点
            while(cur !== slow){
                slow = slow.next
                cur = cur.next
            }
            return cur
        }

    }
    return null
};

收工!