思科和橫河電機面試題。通過一次遍曆找到單鏈表中倒數第n個節點,鏈表可能相當大,可使用輔助空間,但是輔助空間的數目必須固定,不能和n有關。
單向鏈表的特點是遍曆到末尾後不能反向重數N個節點。因此必須在到達尾部的同時找到倒數第N個節點。
不管是順數n個還是倒數n個,其實都是距離-尺規問題。尺規是一段距離可以用線段的兩個端點來衡量,我們能夠判斷倒數第一個節點,因為他的next==NULL。如果我們用兩個指標,並保持他們的距離為n,那麼當這個線段的右端指向末尾節點時,左端節點就指向倒數第n個節點。
iNode * GetLastNnode(iNode * head, int n)
{
iNode * pfirst=head;
iNode *psecond=head;
int counter;
//第1步:建立尺規,移動pfirst N步
for(counter=0; counter<n; counter++) {
if((NULL == pfirst)
break; // 此時pfirst->next無意義
pfirst=pfirst->next;
}
if(n != counter) //長度不夠n,未找到倒數第n個節點
return NULL;
//第2步:保持距離讓尺規向右移動,直到右端指向末尾,左端即結果
while(pfirst!=NULL) {
pfirst=pfirst->next;
psecond=psecond->next;
}
return psecond;
}
iNode * GetLastNnode ( iNode *head, int n)
{
iNode * pfirst = head;
iNode * psecond = NULL;//可能沒有n個
while( n-- > 0 && (pfirst!= NULL)
{
pfirst = pfirst ->next;
}
if(pfirst!= NULL)// 有n個節點
psecond = head;
while(pfirst!=NULL)
{
pfirst = pfirst ->next;
psecond = psecond ->next;
}
return psecond; //只有一個出口,無論是否有n個節點,都能返回正確值
}
一次遍曆單向鏈表找到中間節點
和上面的思路類似,設定2個指標,一個走2步時,另一個走1步。那麼一個走到頭時,另一個走到中間。
iNode * GetMiddleNode ( iNode *head)
{
iNode *p1 = head;
iNode *p2 = p1;
while( p2 )
{
p2 = p2->next;
if(p2)
{
p2 = p2->next;
p1=p1->next;
}
}
return p1;
}