請參照書P233-235.
這道題讓我聯想起幾道關於單向鏈表的經典題目:
- 如果判斷一個單項鍊表是否存在環?
- 已知一個單向鏈表存在環,如果找出該環的入口點?
- 已知兩個鏈表相交,如何找出相交的第一個節點?
- 如果對一個單向鏈表進行反轉?
- 已知一個單向鏈表,不知道該鏈表的頭指針,已知一個節點的指針,如何將該節點從鏈表中刪除?
題1:設置兩個指針(p1, p2),初始值都指向頭,p1每次前進一步,p2每次前進二步,如果鏈表存在環,則p2先進入環, p1後進入環,兩個指針在環中走動,必定相遇。
題2:根據題1的結果,假定鏈表長爲L,環長爲c,鏈表頭到入口點距離爲x,入口點到相遇點的距離爲y,z爲相遇點回到入口點的距離。
L=x+y+z
假定p1,p2指針相遇時,p2指針在環中走了n圈,則有
x+y=nc
所以,x=nc-y=(n-1)c+(L-x)-y=(n-1)c+z
由公式得出:將p1指向表頭,p2指向相遇點,p1,p2同時一步一步前進,當p1前進x步時,p1剛好在入口點,p2在前進了n-1個環後,也回到入口點,這時兩個指針指向同一個節點,該節點就是入口點。
題3:題跟題2一樣,可以將一個鏈表的尾節點指向另外一個,這樣就問題2一樣的解法了。當然,完成時,記得把指針重新置空。
另外一個辦法,就是分別計算出兩個鏈表的長度,分別爲maxL,minL,分別設置指針p1,p2指向兩個鏈表,p1指針指向長鏈表,p1先前進maxL-minL的距離,然後兩個指針同時前進,當p1和p2指向同一個節點時,該節點即爲相交的第一個節點,如果沒有找到,就表示這兩個鏈表不相交
題4:
解法一:可以設置三個指針,pre,cur,next,pre
node *pre=NULL;
node *next=NULL;
node *cur=head;
while(!cur)
{
next=cur->next;
cur->next=pre;
pre=cur;
cur=next;
}
解法二:使用遞歸
node *newRoot;
node *reverseNode(node *cur)
{
if(!cur || !cur.next)
{
newRoot=root;
return cur;
}
node *tmp= reverseNode(cur->next);
tmp->next=cur;
return cur;
}
題5:因爲不知道鏈表的頭指針,因此當前節點(B)如果被刪除,鏈表將斷裂,因此可以用一個指針指向當前節點(B)的下一個節點(C),然後將下一個節點複製到當前節點,這樣當前節點數據就爲下一個節點的數據了,而且指向了下下個節點,然後刪除C節點。
附上《編程之美》該題的三頁: