【算法】判断链表中是否有环
判断链表是否有环,一般的做法是使用快慢指针的方法来判断,今天想给大家介绍另一种更想法奇特的算法——链表破坏法(仅做参考)
前置说明
链表的存储结构如下,主要包括val和next(为了简单就没有把他变成私有变量)
1 public class ListNode { 2 public int val; 3 public ListNode next; 4 public ListNode(int x) { 5 val = x; 6 next = null; 7 } 8 }
快慢指针法
算法说明:
- 设置慢指针slow和快指针fast,初始化都在头结点
- fast指针每次比slow指针多走一步
- 判断,如果快指针快指针为空,那认为到达了链表顶端,那么就没有环
- 判断,如果某一次循环中快指针撞上了慢指针,那么表示形成了闭环(但这并不是环的入口)
优点:
- 保持链表结构。
缺点:
- 仅能判断是否有环,无法同时找到入口节点信息
1 public boolean hasCycle(ListNode head) { 2 ListNode slow = head; 3 ListNode fast = head; 4 while (slow!=null && fast!=null && fast.next!=null){ 5 slow = slow.next; 6 fast = fast.next.next; 7 if (fast == slow){ 8 return true; 9 } 10 } 11 return false; 12 }
链表破坏法
算法说明:
- 遍历链表,将每个节点都指向head节点
- 判断是否当前节点的next已经指向的head节点,如果是,则表示当前节点是环的入口(有环)
- 如果一直都没有2的情况发生,且遇到节点为null,表示达到了节点尾部(无环)
优点:
- 可以快速判断是否有环以及环入口。
缺点:
- 会破坏原始链表结构。
1 public boolean hasCycle(ListNode head) { 2 ListNode node = head; 3 ListNode next = null; 4 while (node!=null) { 5 if (node.next == head) { 6 return true; 7 } 8 next = node.next; 9 node.next = head; 10 node = next; 11 } 12 return false; 13 }