寫在前面:
劍指offer中,面試中,都很經典的一個問題,今天進行總結,其實從這個題目中,可以解析,延伸出多個問題,如:鏈表中是否存在有環,如果有環,求鏈表中環的入口結點,環的長度是多少等。
題目連結:https://www.nowcoder.com/questionTerminal/253d2c59ec3e4bc68da16833f79a38e4
(1)鏈表中是否存在有環
判斷鏈表中是否有環相對較為簡單,這個問題的思路是,設定兩個指標,一個快指標,一個慢指標,快指標每次走2步,而慢指標每次走1步,這樣,如果鏈表中存在環,那麼兩個指標就一定會在環中相遇。
代碼實現:
public ListNode EntryNodeOfLoop(ListNode pHead) {if (pHead == null || pHead.next == null) {return null;}ListNode fast = pHead;ListNode slow = pHead;while (fast != null && slow != null) {// 快指標每次兩步,慢指標每次一步fast = fast.next.next;slow = slow.next;if (fast.val == slow.val) { return fast;}}return null;}
(2)鏈表中環的長度
在問題1中,求出的相遇點位置,讓slow節點不動,fast節點每次走一步,下一次再相遇時,查看fast所走的步數則為,環的長度。
代碼實現:
public int EntryNodeOfLoop(ListNode pHead) {if (pHead == null || pHead.next == null) {return 0;}ListNode fast = pHead;ListNode slow = pHead;while (fast != null && slow != null) {// 快指標每次兩步,慢指標每次一步fast = fast.next.next;slow = slow.next;if (fast.val == slow.val) {ListNode p = fast.next;ListNode q = slow;int step = 1;while (p.val != q.val) {p = p.next;step++;}return step;}}return 0;} step的值,即為鏈表的環的長度。
(3)鏈表中環的入口結點
這個問題是劍指offer的原題,這個問題的解題思路是:當我們在第一個問題中,找到了快慢指標在鏈表中的相遇點之後,我們重新設定兩個節點,節點p指向前端節點,節點q指向剛剛相遇的節點(fast或者slow都可以)。節點p和節點q每次都是走1步,兩個第一次相遇的節點位置,則為鏈表中環的入口結點。
代碼實現:
/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; }}*/public class Solution {public ListNode EntryNodeOfLoop(ListNode pHead) {if (pHead == null || pHead.next == null) {return null;}ListNode fast = pHead;ListNode slow = pHead;while (fast != null && slow != null) {// 快指標每次兩步,慢指標每次一步fast = fast.next.next;slow = slow.next;if (fast.val == slow.val) {// 相遇之後,快指標指向頭指標,慢指標在相遇位置,每次一步ListNode p = pHead;ListNode q = slow;while (p.val != q.val) {p=p.next;q=q.next;}return p;}}return null;}}