【演算法】判斷連結串列中是否有環
阿新 • • 發佈:2021-09-06
判斷連結串列是否有環,一般的做法是使用快慢指標的方法來判斷,今天想給大家介紹另一種更想法奇特的演算法——連結串列破壞法(僅做參考)
前置說明
連結串列的儲存結構如下,主要包括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 }