前面一篇博文簡要地講了下我在筆試準備過程中碰到過的有關字串的題目,現在再提下有關鍊錶的題目
做有關鍊錶的題目最好畫圖,這樣有助於理解
1、單向鍊錶逆序
2、有序鍊錶合併
3、雙向鍊錶刪除結點
4、尋找鍊錶中間結點
5、判斷乙個鍊錶是否有環
1、單向鍊錶逆序
(1) 具有煉表頭的單鏈表
student *reverse(student *stu)
printf("p1 = %d,next = %dn ",p1->number,p1->next->number);
stu->next=p1;
//將煉表頭節點指向p1
return stu;}
核心思想:
p=head->next->next;
s=head->next;
head->next->next=null;
while(p)
(2) 無鍊表頭單鏈表
typedef struct student
student;
student *reverse2(student *stu)
printf("p1 = %d,next = %d\n ",p1->number,p1->next->number);
stu=p1; //將鍊錶第乙個節點指向p1
return stu;}
(3) 只用乙個變數,遞迴
list* recurreverse(list* p, list* head)
else
}node* reverse(node * head)
2、有序鍊錶合併
(1)遞迴方法。
比如有下面兩個鍊錶:
鍊錶1:1->3->5
鍊錶2:2->4->6
遞迴方法的步驟如下:
(1)比較鍊錶1和鍊錶2的第乙個節點資料,由於1<2,因此把結果煉表頭節點指向鍊錶1中的第乙個節點,即資料1所在的節點。
(2)對剩餘的鍊錶1(3->5)和鍊錶2再呼叫本過程,比較得到結果鍊錶的第二個節點,即2與3比較得到2。此時合併後的鍊錶節點為1->2。
接下來的過程類似(2),如此遞迴直到兩個鍊錶的節點都被加到結果鍊錶中
node * mergerecursive(node *head1, node *head2)
if (head2 == null)
if ( head1->data < head2->data )
else
return head ; }
(2)非遞迴方法。有鍊表頭
node* merge2(node* head1, node* head2)
else }
res->next = p ? p : q; //p或q有剩,把剩下的鍊錶插入到結果鍊錶後
return ret; }
還可以借助第三個鍊錶,只是這樣的話需要的空間會大點
node *head3,*temp;
head3->next=null;
temp=head3;//儲存表頭
p=head1->next;
q=head2->next;
while(p!=null&&q!=null)
else
if(p==null)
head3->next=q;
else
head3->next=p;
head3=temp; }
3、雙向鍊錶刪除結點
dnode *deletenode(dnode *head,dnode *node)
else if(node->next == null)
else
free(node);
return head;
}4、尋找鍊錶中間結點
【方法1】普通的方法很簡單,首先遍歷一遍單鏈表以確定單鏈表的長度l。然後再次從頭節點出發迴圈l/2次找到單鏈表的中間節點。演算法複雜度為o(l+l/2)=o(3l/2)。
【方法2】使用快慢指標。設定兩個指向第乙個結點的指標,乙個(p)一次走乙個,乙個(q)一次走兩個。當走的快的到達鍊錶尾部(q->next==null ||q->next->next==null)時,慢的就指向中間結點(快指標到鍊錶尾部時,當鍊表長度為奇數時,慢指標指向的即是鍊錶中間指標,當鍊表長度為偶數時,慢指標指向的結點和慢指標指向結點的下乙個結點都是鍊錶的中間結點)
node *findmid(node *head) // 有鍊表頭
return slow;
}node *findmid(node *head) // 無鍊表頭
return slow;
}5、判斷乙個鍊錶是否有環
(1)判斷是否有環。
設定兩個指標(fast, slow),初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入環,而slow後進入環,兩個指標必定 相遇。(當然,fast先行頭到尾部為null,則為無環鏈表)
(2)找到環的入口點
當fast若與slow相遇時,slow肯定沒有走遍歷完鍊錶,而fast已經在環內迴圈了n圈(1<=n)。假設slow走了s步,則 fast走了2s步(fast步數還等於s 加上在環上多轉的n圈),設環長為r,則:
2s = s + nr
s= nr
設整個鍊錶長l,入口環與相遇點距離為x,起點到環入口點的距離為a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + l - a
a = (n-1)r + (l – a – x)
(l – a – x)為相遇點到環入口點的距離,由此可知,從煉表頭到環入口點等於(n-1)迴圈內環+相遇點到環入口點,於是我們從煉表頭、與相遇點分別設乙個指標,每 次各走一步,兩個指標必定相遇,且相遇第一點為環入口點。
node *findcircle(node *head)
return fast;}}
return null;
}
ps:感覺鍊錶經常在面試中遇到,一般面試官經常會要你進行紙上程式設計,考查你的動手能力等等。。。
未完待續。。。
實習小結十四 無題
又是將近乙個月沒有更新了,這個月蠻倒霉的,誒誒誒 日子還是要過的 最近做的應該是乙個calendar模組,以及將post模組從原來的mysql遷徙到mongo資料庫中,不得不說nosql在資料字段比較多的時候,還是蠻方便的,不需要講很多規矩,基本不會影響action的除錯,還可以儲存陣列等等。然後,...
實習整理 十六
感覺關於實習準備的這部分已經寫得差不多了,沒有啥可寫的了,寫下卡特蘭數吧,這個在筆試中也有涉及到。定理 n個 1和n個 1構成的2n項,其部分和滿足大於等於0的數列其個數則為第n個卡特蘭數 卡塔蘭數的一般項公式為 總結了一下,最典型的四類應用 1.括號化問題 矩陣鏈乘 p a1 a2 a3 an,依...
前端 實習面試整理
乙個函式節流提高效能 var canrun true document.getelementbyid throttle onscroll function canrun false settimeout function 500 延遲問題 function delay timer timer 使用p...