單鏈表反**下面給出兩種可能的實現。
普通版:
void reverse(node*& head)
head->next = null;
head = pprev;
}
遞迴版:
node* reverse( node* pnode, node*& head)
node* temp = reserve(pnode->next, head);// 遞迴
temp->next = pnode;// 將下一節點置為當前節點,既前置節點
return pnode;// 返回當前節點
}
使用反轉鍊錶的方法, 每過乙個節點就把該節點的指標反向。若存在
環,反轉next指標最終會走到鍊錶頭部。若沒有環,反轉next指標會破壞鍊錶結構(使鍊錶反向), 所以為還原鍊錶,需要把鍊錶再反向一次。 這種方法的空間複雜度是o(1), 實事上我們使用了3個額外指標;而時間複雜度是o(n), 我們最多2次遍歷整個鍊錶(當鍊表中沒有環的時候)。下面給出乙個實現,但最大的問題是:若存在環,則無法還原到鍊錶的原狀態。
bool reverse(node *head)
node *temp = curr;
curr = next;
next = next->next;
curr->next = temp;
}/* at the end of list, so there is no loop, let's reverse the list back */
next = curr->next;
curr ->next = null;
while(next!=null)
return false;
}
3. 快慢指標。 時間o(n),空間o(1),使用兩個指標。(ref:
判斷環的存在:設定兩個指標(fast, slow),初始值都指向頭,slow每次前進一步,fast每次前進二步。如果鍊錶存在環,則fast必定先進入環,而slow後進入環,兩個指標必定相遇。(當然,fast先行頭到尾部為null,則是無環鏈表)。
bool i***itsloop(slist * head)
return ! (fast == null || fast -> next == null);
}
尋找環的入口點: 當fast按照每次2步,slow每次一步的方式走,發現fast和slow重合,確定了單向鍊錶有環路。接下來,讓fast回到鍊錶的頭部,重新走,每次步長1,那麼當fast和slow再次相遇的時候,就是環路的入口了。
證明:在fast和slow第一次相遇的時候,假定slow走了n步,環路的入口是在p步,那麼
slow走的路徑: p+c = n; c為fast和slow相交點 距離環路入口的距離
fast走的路徑: p+c+k*l = 2*n; l為環路的周長,k是整數
顯然,如果從p+c點開始,slow再走n步的話,還可以回到p+c這個點。
同時,fast從頭開始走,步長為1,經過n步,也會達到p+c這點。
顯然,在這個過程中fast和slow只有前p步驟走的路徑不同。所以當p1和p2再次重合的時候,必然是在鍊錶的環路入口點上。
slist * findloopport(slist * head)
if (fast == null || fast -> next == null)
return null;
slow = head;
while (slow != fast)
return slow;
}
判斷單鏈表是否存在環,尋找單鏈錶環的入口
判斷單鏈表是否存在環,如果存在環,找出環的入口 有乙個單鏈表,其中可能有乙個環,也就是某個節點的next指向的是鍊錶中在它之前的節點,這樣在鍊錶的尾部形成一環。問題 1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如何找到環的入口點?解答 一 判斷鍊錶是否存在環,辦法為 設定兩個指標 fa...
判斷單鏈表是否存在環及尋找環的入口點
判斷乙個單鏈表是否存在環的解法如下 問題1 快慢指標何時相遇,是否迴轉幾十圈,才相遇呢?證明1 設環長為l,slow指標第一次進入環內,fast指標在前方的a節點處 0 0 x a 2x mod l 0 a x mod l 兩邊同時減去x 就是說a x對l求餘應該是0,即a x 0,l,2l 這一系...
判斷單鏈表是否存在環
有乙個單鏈表,其中可能有乙個環,也就是某個節點的next指向的是鍊錶中在它之前的節點,這樣在鍊錶的尾部形成一環。問題 1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如果找到環的入口點?解答 一 判斷鍊錶是否存在環,辦法為 設定兩個指標 fast,slow 初始值都指向頭,slow每次前進...