Remove Loop in Linked List Using Java

2025 年 5 月 5 日 | 阅读 6 分钟

链表中的环是指链表中的一个节点指向了链表中的一个较早的节点,从而形成了一个循环,而不是链表的末尾。检测并移除这个环可以恢复链表的线性结构,防止无限遍历,并提高其在后续操作中的可靠性。

方法:使用哈希

这种方法在遍历链表时使用 HashSet 来存储已访问的节点。如果一个节点被再次访问(已存在于 HashSet 中),则检测到环,并通过更新前一个节点的 next 指针为 null 来移除环。

算法

步骤 1: 创建一个空的 HashSet 来存储已访问的节点,并创建一个 变量 previousNode 来跟踪前一个节点。

步骤 2: 从头节点开始,遍历链表,检查每个节点。

步骤 3: 对于每个节点,检查它是否已存在于 HashSet 中(表示存在环)。如果检测到环,通过设置 previousNode.next = null 来移除它。

步骤 4: 如果未检测到环,则将当前节点添加到 HashSet 中,并移动到下一个节点。

步骤 5: 继续此过程,直到到达链表的末尾(即 headNode 变为 null),确保如果存在环则将其移除。

实施

文件名:LinkedListLoopRemover.java

输出

 
5 12 7 3 8   

时间复杂度: O(N) - 每个节点仅遍历一次。

辅助空间: O(N) - 使用 HashSet 存储已访问的节点。

方法:Floyd 循环检测算法

Floyd 循环检测算法,也称为龟兔赛跑方法,使用两个以不同速度移动的指针来检测链表中的环。如果存在循环,两个指针将在循环内部相遇,从而能够以恒定的空间复杂度有效地检测和移除环。

算法

步骤 1: 将两个指针 slowPointer 和 fastPointer 设置在链表的头部。

步骤 2: 将 slowPointer 向前移动一步,将 fastPointer 向前移动两步。如果它们相遇,则检测到环。

步骤 3: 将 slowPointer 重置到头部。一次一步地移动 slowPointer 和 fastPointer,直到它们在循环的起点相遇。

步骤 4: 一旦找到循环的起点,就将最后一个节点的 nextNode 指针设置为 null,以打破循环。

步骤 5: 从头部打印链表,以确认环已被移除。

实施

文件名:LinkedListLoopRemover.java

输出

 
100 200 300 400 500   

时间复杂度:O(n)

辅助空间复杂度: O(1)