轉自:http://blog.sina.com.cn/s/blog_54b2ce380100uqwr.html
某本書上面說了,鏈表這個東西,實際用的並不多,但是可以提供很好的考察面試者編程技巧和思維能力的素材。這裏總結一下,見過的面試題和對應的候選解法。
題一、 給定單鏈表,檢測是否有環。
使用兩個指針p1,p2從鏈表頭開始遍歷,p1每次前進一步,p2每次前進兩步。如果p2到達鏈表尾部,說明無環,否則p1、p2必然會在某個時刻相遇(p1==p2),從而檢測到鏈表中有環。
http://ostermiller.org/find_loop_singly_linked_list.html
這篇文章講了很多好的壞得相關算法。
題二、 給定兩個單鏈表(head1, head2),檢測兩個鏈表是否有交點,如果有返回第一個交點。
如果head1==head2,那麼顯然相交,直接返回head1。
否則,分別從head1,head2開始遍歷兩個鏈表獲得其長度len1與len2。假設len1>=len2,那麼指針p1由head1開始向後 移動len1-len2步。指針p2=head2,下面p1、p2每次向後前進一步並比較p1p2是否相等,如果相等即返回該結點,否則說明兩個鏈表沒有 交點。
題三、 給定單鏈表(head),如果有環的話請返回從頭結點進入環的第一個節點。
運用題一,我們可以檢查鏈表中是否有環。
如果有環,那麼p1p2重合點p必然在環中。從p點斷開環,方法爲:p1=p, p2=p->next, p->next=NULL。此時,原單鏈表可以看作兩條單鏈表,一條從head開始,另一條從p2開始,於是運用題二的方法,我們找到它們的第一個交點即爲所求。
也可以不斷開環。設重合點爲p3,從p3開始遍歷這個環,同時從表頭開始走,檢查每步是否在那個環中。這個方法大概有nlogn。
使用快慢指針,第一次相遇,表明存在循環。繼續快慢指針,第二次相遇,得到的iteration步長爲環的長度。分別從相遇點和第一個節點出發,都是步長爲1的指針,當相遇時,得到的iteration步長爲環首的位置。
題四、只給定單鏈表中某個結點p(並非最後一個結點,即p->next!=NULL)指針,刪除該結點。
辦法很簡單,首先是放p中數據,然後將p->next的數據copy入p中,接下來刪除p->next即可。
題五、只給定單鏈表中某個結點p(非空結點),在p前面插入一個結點。
辦法與前者類似,首先分配一個結點q,將q插入在p後,接下來將p中的數據copy入q中,然後再將要插入的數據記錄在p中。
題六、給定單鏈表頭結點,刪除鏈表中倒數第k個結點。
使用兩個節點p1,p2,p1初始化指向頭結點,p2一直指向p1後第k個節點,兩個結點平行向後移動直到p2到達鏈表尾部(NULL),然後根據p1刪除對應結點。
題七、鏈表排序
鏈表排序最好使用歸併排序算法。堆排序、快速排序這些在數組排序時性能非常好的算法,在鏈表只能“順序訪問”的魔咒下無法施展能力;但是歸併排序卻如魚得水,非但保持了它O(nlogn)的時間複雜度,而且它在數組排序中廣受詬病的空間複雜度在鏈表排序中也從O(n)降到了O(1)。真是好得不得了啊,哈哈。以上程序是遞推法的程序,另外值得一說的是看看那個時間複雜度,是不是有點眼熟?對!這就是分治法的時間複雜度,歸併排序又是divide and conquer。
double cmp(ListNode *p ,ListNode *q)
{return (p->keyVal - q->keyVal);}
ListNode* mergeSortList(ListNode *head)
{
ListNode *p, *q, *tail, *e;
int nstep = 1;
int nmerges = 0;
int i;
int psize, qsize;
if (head == NULL || head->next == NULL)
{return head;}
while (1)
{ p = head;
tail = NULL;
nmerges = 0;
while (p)
{ nmerges++; q = p; psize = 0;
for (i = 0; i < nstep; i++){
psize++;
q = q->next;
if (q == NULL)break;
}
qsize = nstep;
while (psize >0 || (qsize >0 && q))
{
if (psize == 0 ){e = q; q = q->next; qsize--;}
elseif (q == NULL || qsize == 0){e = p; p = p->next; psize--;}
elseif (cmp(p,q) <= 0){e = p; p = p->next; psize--;}
else{e = q; q = q->next; qsize--;}