环形链表(给定一个链表,判断链表中是否有环。)、环形链表 II(给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。)

141. 环形链表

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

为了表示给定链表中的环,我们使用整数 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
解释:链表中没有环。

分析:

设ListNode型的快指针fastNode,慢指针slowNode,遍历链表,慢指针每次走一步,快指针每次走两步,若快慢指针最终相遇,说明存在环,若fastNode != null 或者 fastNode.next != null,说明遍历完毕还是没有遇到,不存在环。

代码:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fastNode = head;
        ListNode slowNode = head;
        while(fastNode != null && fastNode.next != null){
            slowNode = slowNode.next;
            fastNode = fastNode.next.next;
            if(slowNode == fastNode){
                return true;
            }
        }
        return false;
    }
}

142. 环形链表 II

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

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

说明:不允许修改给定的链表。

以下图同上:

示例 1:

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

示例 2:

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

示例 3:

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

分析:

方法:设ListNode型的快指针fastNode,慢指针slowNode,遍历链表,慢指针每次走一步,快指针每次走两步,若快慢指针相遇,说明存在环,因为遍历完毕而跳出循环,说明没有相遇,没有相遇直接返回null,此时将快指针指向头节点,快、慢指针每次都只走一步,再相遇的节点就是入环的节点。

原因:用以下图来解释这样做为什么会找到入环的节点。

M表示fastNode、slowNode第一次相遇的节点,设头节点到入环节点的距离为a,设入环节点到M节点的距离为b,设慢指针走过的长度是n,那么快指针走过的长度就为2*n,L表示环的长度,且a+b=n; a+b+k*L=2*n;由上式可以推导出k*L=a+b=n;而指针由入环到M走过的长度刚好为b,将fastNode指向head,fastNode到入环节点走a步,slowNode到入环节点走k*L-b=a步。走的步数相同,因此它们再次相遇的节点就是入环节点。

代码:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null || head.next == null){
            return null;
        }
        ListNode slowNode = head;
        ListNode fastNode = head;
        //相遇的节点
        while(fastNode != null && fastNode.next != null){
            slowNode = slowNode.next;
            fastNode = fastNode.next.next;
            if(slowNode == fastNode){
                break;
            }
        }
        if(slowNode != fastNode){
            return null;
        }
        fastNode = head;
        while(fastNode != slowNode){
            slowNode = slowNode.next;
            fastNode = fastNode.next;
        }  
        return slowNode;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43109561/article/details/89072424