1. 程式人生 > 其它 >【演算法】判斷連結串列中是否有環

【演算法】判斷連結串列中是否有環

判斷連結串列是否有環,一般的做法是使用快慢指標的方法來判斷,今天想給大家介紹另一種更想法奇特的演算法——連結串列破壞法(僅做參考)

前置說明

連結串列的儲存結構如下,主要包括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 }

快慢指標法

演算法說明:

  1. 設定慢指標slow和快指標fast,初始化都在頭結點
  2. fast指標每次比slow指標多走一步
  3. 判斷,如果快指標快指標為空,那認為到達了連結串列頂端,那麼就沒有環
  4. 判斷,如果某一次迴圈中快指標撞上了慢指標,那麼表示形成了閉環(但這並不是環的入口)

優點:

  1. 保持連結串列結構。

缺點:

  1. 僅能判斷是否有環,無法同時找到入口節點資訊
 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 }

連結串列破壞法

演算法說明:

  1. 遍歷連結串列,將每個節點都指向head節點
  2. 判斷是否當前節點的next已經指向的head節點,如果是,則表示當前節點是環的入口(有環)
  3. 如果一直都沒有2的情況發生,且遇到節點為null,表示達到了節點尾部(無環)

優點:

  1. 可以快速判斷是否有環以及環入口。

缺點:

  1. 會破壞原始連結串列結構。
 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     }