題目:
輸入乙個單向鍊錶,輸出該鍊錶中倒數第k個結點。鍊錶的倒數第0個結點為鍊錶的尾指標。
方法一:
假設整個鍊錶有
n個結點,那麼倒數第
k個結點是從頭結點開始的第
n-k-1
個結點(從
0開始計數)。如果我們能夠得到鍊錶中結點的個數
n,那我們只要從頭結點開始往後走
n-k-1
步就可以了。如何得到結點數
n?這個不難,只需要從頭開始遍歷鍊錶,每經過乙個結點,計數器加一就行了。
給出**:
#include #include typedef struct node
linklist;
void createlist(linklist *l); //建立乙個鍊錶
int getlength(linklist *l); //獲取鍊錶長度
int output(linklist *l,int len,int k); //輸出長度為len的鍊錶的倒數第k個結點的值
int main()
printf("%d\n\n",output(l,n,k));
} return 0;
}void createlist(linklist *l)
}int getlength(linklist *l)
return count;
}int output(linklist*l,int len,int k)
return s->value;
}
這種思路的時間複雜度是
o(n)
,但需要遍歷鍊錶兩次。第一次得到鍊錶中結點個數
n,第二次得到從頭結點開始的第
n-k-1
個結點即倒數第
k個結點。
如果鍊錶的結點數不多,這是一種很好的方法。但如果輸入的鍊錶的結點個數很多,有可能不能一次性把整個鍊錶都從 硬碟讀入物理記憶體,那麼遍歷兩遍意味著乙個結點需要兩次從硬碟讀入到物理記憶體。我們知道把資料從硬碟讀入到記憶體是非常耗時間的操作。我們能不能把鍊錶遍歷 的次數減少到
1?如果可以,將能有效地提高**執行的時間效率。
方法二:
如果我們在遍歷時維持兩個指標,第乙個指標從鍊錶的頭指標開始遍歷,在第
k-1步之前,第二個指標保持不動;在第
k-1步開始,第二個指標也開始從鍊錶的頭指標開始遍歷。由於兩個指標的距離保持在
k-1,當第乙個(走在前面的)指標到達鍊錶的尾結點時,第二個指標(走在後面的)指標正好是倒數第
k個結點。
這種思路只需要遍歷鍊錶一次。對於很長的鍊錶,只需要把每個結點從硬碟匯入到記憶體一次。因此這一方法的時間效率前面的方法要高。
給出**:
#include #include typedef struct node
linklist;
void createlist(linklist *l); //建立乙個鍊錶
void output(linklist *l,int k); //輸出倒數第k個結點的值
int main()
return 0;
}void createlist(linklist *l)
}void output(linklist*l,int k)
for (i=0;inext;
if (tail==null) //如果k輸入過大,退出
}while(tail!=null&&head!=null) //tail和head指標一起走
printf("%d\n",head->value);
}
擴充套件:
和這道題類似的題目還有:輸入乙個單向鍊錶。如果該鍊錶的結點數為奇數,輸出中間的結點;如果鍊錶結點數為偶數,輸出中間兩個結點前面的乙個。如果各位感興趣,請自己分析並編寫**。
輸入乙個鍊錶,輸出該鍊錶中倒數第k個結點。
1,問題 輸入乙個鍊錶,輸出該鍊錶中倒數第k個結點。2,想法都在 裡標註了 struct listnode class solution int count 0 listnode temp plisthead while plisthead int m count k 倒數第k個,是順數第count...
輸入乙個鍊錶,輸出該鍊錶中倒數第k個結點
思路 兩個指標,先讓第乙個指標和第二個指標都指向頭結點,然後再讓第乙個指正走 k 1 步,到達第k個節點。然後兩個指標同時往後移動,當第乙個結點到達末尾的時候,第二個結點所在位置就是倒數第k個節點了。public class solution public listnode findkthtotai...
輸入乙個鍊錶,輸出該鍊錶中倒數第k個結點。
題目描述 輸入乙個鍊錶,輸出該鍊錶中倒數第k個結點。解題思路 1.先遍歷鍊錶,獲得鍊錶中的總結點數。2.倒數第k個元素,即為順數第 size k 1 個元素。3.遍歷鍊錶,獲得第 size k 1的元素。public class listnode public class solution 統計鍊錶...