【算法分析与设计】环形链表

       个人主页:五敷有你      

 系列专栏:算法分析与设计

⛺️稳中求进,晒太阳

题目

给你一个链表的头节点 head ,判断链表中是否有环。

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

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例

示例 1:

【算法分析与设计】环形链表_第1张图片

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

示例 2:

【算法分析与设计】环形链表_第2张图片

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

示例 3:

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

思路

快慢指针

        你可以使用快慢指针的方法来判断链表是否有环。快指针每次移动两步,慢指针每次移动一步,如果存在环,快指针最终会追上慢指针。

        先检查头节点和头节点的下一个节点是否为null,如果是,则返回false。然后使用快慢指针方法,初始化快指针为头节点的下一个节点,慢指针为头节点,然后在一个while循环中,快慢指针分别向前移动。如果快指针或快指针的下一个节点为null,说明链表无环,返回false;如果快慢指针相遇,说明链表有环,返回true。

Set集合

        定义了一个HashSet来存储已经遍历过的节点。然后,我们从头节点开始遍历链表,对于每个节点,我们检查它是否已经在HashSet中存在,如果存在则说明链表有环,返回true;否则,将节点加入HashSet中。如果遍历完整个链表都没有发现环,则返回false。

代码实现

快慢指针

/**
 * 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) {
      HashSet set = new HashSet<>();
        ListNode current = head;
        
        while (current != null) {
            if (set.contains(current)) {
                return true; // 发现环
            }
            set.add(current);
            current = current.next;
        }
        
        return false; // 遍历完整个链表都没发现环
   
    }
}

Set集合

/**
 * 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) {
      HashSet set = new HashSet<>();
        ListNode current = head;
        
        while (current != null) {
            if (set.contains(current)) {
                return true; // 发现环
            }
            set.add(current);
            current = current.next;
        }
        
        return false; // 遍历完整个链表都没发现环
   
    }
}

运行结果

快慢指针

  • 在这种方法中,我们使用两个指针,一个慢指针和一个快指针。慢指针每次移动一步,快指针每次移动两步。
  • 在最坏情况下,如果链表中没有环,那么快指针将会先到达链表的末尾,此时时间复杂度为O(n),其中n是链表中节点的个数。
  • 如果链表中有环,快慢指针都会进入环中,因为快指针每次比慢指针多走一步,所以它们最终会相遇,时间复杂度也是O(n),其中n是环的长度。这是因为在环中,快指针每次能够靠近慢指针一步,因此需要经过环的长度次数才能相遇。

因此,使用快慢指针的方法的时间复杂度是O(n)。

【算法分析与设计】环形链表_第3张图片

Set集合

  • 在这种方法中,我们使用一个HashSet来存储已经访问过的节点。
  • 在最坏情况下,如果链表中没有环,那么我们需要遍历整个链表并将每个节点加入HashSet中,时间复杂度为O(n),其中n是链表中节点的个数。
  • 如果链表中有环,我们同样需要遍历整个链表,但在某个时刻我们会发现HashSet中已经存在了某个节点,这时就说明链表有环。因此时间复杂度依然是O(n),其中n是链表中节点的个数。

因此,使用HashSet的方法的时间复杂度也是O(n)。

【算法分析与设计】环形链表_第4张图片

你可能感兴趣的:(算法分析与设计,算法,链表,数据结构)