cc150:實現一個演算法從一個單鏈表中返回倒數第n個元素
實現一個演算法從一個單鏈表中返回倒數第n個元素。
解答
這道題的考點在於我們怎麼在一個單鏈表中找到倒數第n個元素? 由於是單鏈表,所以我們沒辦法從最後一個元素數起,然後數n個得到答案。 但這種最直觀的思路顯然是沒錯的,那我們有沒有辦法通過別的方式,從最後的元素數起數 n個來得到我們想要的答案呢。這個次序顛倒的思路可以讓我們聯想到一種資料結構:棧。我們如果遍歷一遍單鏈表,將其中的元素壓棧,然後再將元素一一出棧。那麼, 第n個出棧
的元素就是我們想要的。那我們是不是需要顯式地用棧這麼一個結構來做這個問題呢?答案是否。看到棧,我們應當
要想到遞迴,它是一種天然使用棧的方式。所以,第一種解決方案用遞迴,讓棧自己幫我們從連結串列的最後一個元素數起。思路很簡單,如果指向連結串列的指標還未空,就不斷遞迴。當指標為空時開始退遞迴,這個過程n不斷減1,直接等於1,即可把棧中當前的元素取出。
遞迴的特點就是理解直接,程式碼短小。所以,很多遞迴程式碼看起來都很漂亮(不包括我這個
哈,還用了兩個全域性變數,比較不美觀)。
void findNthToLast1(node *head){
if(head==NULL) return;
findNthToLast1(head->next);
if(nn==1) pp = head;
--nn;
}
除了遞迴,這道題目還有別的方法還做嗎? 答案
還是有。雖然我們沒辦法從單鏈表的最後一個元素往前數,但如果我們維護兩個指標, 它們之間的距離為n。然後,我將這兩個指標同步地在這個單鏈表上移動,保持它們的距離 為n不變。那麼,當第二個指標指到空時,第一個指標即為所求。很tricky的方法, 將這個問題很漂亮地解決了。
node* findNthToLast(node *head, int n) {
if(head==NULL || n < 1) return NULL;
node *p = head,*q = head;
while(n > 0 && q){
q = q->next;
--n;
}
if(n > 0)
return NULL;
while(q) {
p = q->next;
q = q->next;
}
return p;
}