找到环形链表的起始点

477 阅读2分钟

1. 找到环形链表的起始点

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 --引自力扣 #### 环形链表 II

判断是否是环形链表

1.2 利用快慢指针

未命名文件 (5).png

解题思路:也是一样先把这个转成走格子的游戏,假设小A同学走到起始点需要走a步,此时小B同学走了2a+1,距离起始点a+1步。假设小A同学走到x的位置与小B同学相遇,则x-a = 2(x -1) + 1; x = a - 1,也就是说小A同学如果走到相遇的地方则需要走a-1步,距离起始点是a+1步。

相遇后让小B同学往前多走一步,则距离起始点a步,再将小A同学放到第一个格子前,小A同学距离起始点也是a步,然后小A同学和小B每次都向前走一步,他们相遇的地方就是环的起始点。

代码实现如下:

 function ListNode(val) {
     this.val = val;
     this.next = null;
 }

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var detectCycle = function(head) {
    if (!head) return null;
    if (!head.next) return null;
    if (!head.next.next) return null;
    let p = head;
    let q = head.next.next
    while(q && q.next && q !== p) {
        p = p.next;
        q = q.next.next;
    }
    if (!q || !q.next) {
        return null;
    }
    q = q.next.next;
    p = head;
    while(q !== p) {
        q = q.next;
        p = p.next;
    }
    return q;
};

1.2 利用数组和Set实现

解题思路:这个其实就是将所有的链表节点存放在数组或者Set当中,然后判断是否重复出现,而第一次出现的重复节点就是起始点。先遍历链表,然后判断数组或者Set当中是否存在相同的节点,如果是则是则返回当前节点。

代码实现如下

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

/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var detectCycle = function(head) {
    const set = new Set();
    let curNode = head;
    while(curNode) {
        if (set.has(curNode)) {
            return curNode;
        }
        set.add(curNode);
        curNode = curNode.next;
    }
    return null;
};