1. 給定單鏈表,檢測是否有環。如果有環,則求出進入環的第乙個節點。
判斷單向鍊錶是否有環,可以採用快指標與慢指標的方式來解決。即定義乙個快指標fast和乙個慢指標slow,使得fast每次跳躍兩個節點,slow每次跳躍乙個節點。如果鍊錶沒有環的話,則slow與fast永遠不會相遇(這裡鍊錶至少有兩個節點);如果有環,則fast與slow將會在環中相遇。判斷出煉表有環以後,則需要算出進入環的第乙個節點。在fast與slow第一次相遇後,設定乙個節點pnode從鍊錶的頭部開始遍歷,每次只遍歷乙個節點。這樣,當fast與slow再次相遇時,pnode所處的位置便是環的首部。以下該問題的實現原始碼(c語言描述):
2. 給定兩個單鏈表,檢測兩個鍊錶是否有交點,如果有返回第乙個交點。lnode* getloopnode(lnode* head)
//定義乙個快指標和乙個慢指標
lnode* fast = head;
lnode* slow = head;
while (fast && (fast->next))
}return slow;
} }return null;
}
檢測兩個單鏈表是否有交點是很容易的,因為如果兩個鍊錶有交點,那麼這兩個鍊錶的最後乙個節點必須相同,所以只需比較最後乙個節點即可。但是這種方案是無法求出第乙個交點的,所以需要另闢蹊徑。另外,判斷是否有交點可以轉換成鍊錶是否有環的問題。讓乙個鍊錶的最後乙個節點指向第二個鍊錶的頭結點,這樣的話,如果相交,則新的鍊錶是存在環的,並且交點便是環的入口點。
3. 只給定單鏈表中某個結點p(並非最後乙個結點,即p->next!=null)指標,刪除該結點。
由於沒有給定鍊錶的頭結點,所以無法獲取需要刪除節點的前驅結點,這樣就無法使用常規的方法去解決。在《程式設計之美》這本書裡面給出乙個非常精妙的解法,也就是採用了狸貓換太子的思想。以下是實現原始碼:
void deletenode(lnode* pnode)
//獲取pnode的後驅節點
lnode* qnode = pnode->next;
//將qnode的值賦給pnode,並刪除qnode
pnode->data = qnode->data;
pnode->next = qnode->next;
free(qnode);
}
4. 給定單鏈表頭結點,刪除鍊錶中倒數第k個結點
這個問題的關鍵是需要獲取倒數第k個節點。如何獲取呢?這裡,需要兩個指標p和q,p指向頭結點,q指向距離頭結點為k的節點。這樣p和q每次遍歷乙個節點,當q遍歷到末尾的時候,p指向的節點即為倒數第k個節點。然後刪除即可。以下是實現原始碼(這裡獲取的是倒數第k+1個節點,因為需要刪除的是倒數第k個節點):
void dellastknode(unsigned int k, lnode* head)
lnode* pnode = head;
lnode* qnode = head;
//將qnode遍歷到正數第k + 1個節點
unsigned int i;
for (i = 0; i < k; i++)
//獲取倒數第k + 1個節點
while (qnode->next)
//刪除倒數第k個節點
lnode* temp = pnode->next;
pnode->next = temp->next;
free(temp);
}
鏈表面試題集
1 鍊錶的反轉 注意 1 輸入的煉表頭指標為null或者整個鍊錶只有乙個結點時 2 反轉後鍊錶會不會斷裂 3 返回的反轉之後的頭節點是否為原始鍊錶的尾節點 2 鍊錶中環的入口結點 環中有4個節點,讓指標p1先走4步,然後指標p2和p1一起走,當p1走到入口節點,p2也與p1會相遇。就相當於,我要走9...
鍊錶及鏈表面試題
首先看一下順序表和煉表的優缺點,分別在什麼場景下使用?源 list.h ifndef list h define list h include include include typedef int datatype typedef struct node node,pnode,plist init...
鏈表面試題3 複雜鍊錶
struct clnode 複雜鍊錶 clnode,clpnode,cllist,clplist clpnode clbuynode datatype d clplist data d clplist next null clplist random null return clplist void...