版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
程序員面試題精選100題(10)-在排序數(shù)組中查找和為給定值的兩個(gè)數(shù)字HYPERLINK""\l"m=0&t=1&c=fks_"數(shù)組2023-03-1415:25:01閱讀4663評(píng)論15
字號(hào):大中小
訂閱題目:輸入一個(gè)已經(jīng)按升序排序過的數(shù)組和一個(gè)數(shù)字,在數(shù)組中查找兩個(gè)數(shù),使得它們的和正好是輸入的那個(gè)數(shù)字。規(guī)定期間復(fù)雜度是O(n)。假如有多對(duì)數(shù)字的和等于輸入的數(shù)字,輸出任意一對(duì)即可。例如輸入數(shù)組1、2、4、7、11、15和數(shù)字15。由于4+11=15,因此輸出4和11。分析:假如我們不考慮時(shí)間復(fù)雜度,最簡(jiǎn)樸想法的莫過去先在數(shù)組中固定一個(gè)數(shù)字,再依次判斷數(shù)組中剩下的n-1個(gè)數(shù)字與它的和是不是等于輸入的數(shù)字。可惜這種思緒需要的時(shí)間復(fù)雜度是O(n2)。我們假設(shè)現(xiàn)在隨便在數(shù)組中找到兩個(gè)數(shù)。假如它們的和等于輸入的數(shù)字,那太好了,我們找到了要找的兩個(gè)數(shù)字;假如小于輸入的數(shù)字呢?我們希望兩個(gè)數(shù)字的和再大一點(diǎn)。由于數(shù)組已經(jīng)排好序了,我們是不是可以把較小的數(shù)字的往后面移動(dòng)一個(gè)數(shù)字?由于排在后面的數(shù)字要大一些,那么兩個(gè)數(shù)字的和也要大一些,就有也許等于輸入的數(shù)字了;同樣,當(dāng)兩個(gè)數(shù)字的和大于輸入的數(shù)字的時(shí)候,我們把較大的數(shù)字往前移動(dòng),由于排在數(shù)組前面的數(shù)字要小一些,它們的和就有也許等于輸入的數(shù)字了。我們把前面的思緒整理一下:最初我們找到數(shù)組的第一個(gè)數(shù)字和最后一個(gè)數(shù)字。當(dāng)兩個(gè)數(shù)字的和大于輸入的數(shù)字時(shí),把較大的數(shù)字往前移動(dòng);當(dāng)兩個(gè)數(shù)字的和小于數(shù)字時(shí),把較小的數(shù)字往后移動(dòng);當(dāng)相等時(shí),打完收工。這樣掃描的順序是從數(shù)組的兩端向數(shù)組的中間掃描。問題是這樣的思緒是不是對(duì)的的呢?這需要嚴(yán)格的數(shù)學(xué)證明。感愛好的讀者可以自行證明一下。參考代碼:///////////////////////////////////////////////////////////////////////?//Findtwonumberswithasuminasortedarray?//Output:tureisfoundsuchtwonumbers,otherwisefalse
///////////////////////////////////////////////////////////////////////
boolFindTwoNumbersWithSum
(
?intdata[],//asortedarray
?unsignedintlength,//thelengthofthesortedarray?
intsum,//thesum? int&num1,//thefirstnumber,output
?int&num2//thesecondnumber,output
)?{?boolfound=false;??if(length<1)? returnfound;
?intahead=length-1;? intbehind=0;???while(ahead>behind)
?{? ?longlongcurSum=data[ahead]+data[behind];
//ifthesumoftwonumbersisequaltotheinput?? //wehavefoundthem???if(curSum==sum)
?{? ? num1=dat(yī)a[behind];?? num2=data[ahead];????found=true;? ?break;
??}???//ifthesumoftwonumbersisgreaterthantheinput
? //decreasethegreaternumber? elseif(curSum>sum)
ahead--;
??//ifthesumoftwonumbersislessthantheinput? ?//increasethelessnumber
?else
behind++;
?}
?returnfound;?}擴(kuò)展:假如輸入的數(shù)組是沒有排序的,但知道里面數(shù)字的范圍,其他條件不變,如何在O(n)時(shí)間里找到這兩個(gè)數(shù)字程序員面試題精選100題(11)-求二元查找樹的鏡像HYPERLINK""\l"m=0&t=1&c=fks_"樹2023-03-1509:36:33閱讀3906評(píng)論9
字號(hào):大中小
訂閱題目:輸入一顆二元查找樹,將該樹轉(zhuǎn)換為它的鏡像,即在轉(zhuǎn)換后的二元查找樹中,左子樹的結(jié)點(diǎn)都大于右子樹的結(jié)點(diǎn)。用遞歸和循環(huán)兩種方法完畢樹的鏡像轉(zhuǎn)換。例如輸入:8?/\?610?
/\/\
57911輸出:8?/\
106?
/\
/\
119
75定義二元查找樹的結(jié)點(diǎn)為:structBSTreeNode//anodeinthebinarysearchtree(cuò)(BST)?{? intm_nValue;//valueofnode
?BSTree(cuò)Node*m_pLeft;//leftchildofnode??BSTreeNode*m_pRight;//rightchildofnode?};分析:盡管我們也許一下子不能理解鏡像是什么意思,但上面的例子給我們的直觀感覺,就是互換結(jié)點(diǎn)的左右子樹。我們?cè)囍诒闅v例子中的二元查找樹的同時(shí)來互換每個(gè)結(jié)點(diǎn)的左右子樹。遍歷時(shí)一方面訪問頭結(jié)點(diǎn)8,我們互換它的左右子樹得到:8?/\?106?
/\/\?91157我們發(fā)現(xiàn)兩個(gè)結(jié)點(diǎn)6和10的左右子樹仍然是左結(jié)點(diǎn)的值小于右結(jié)點(diǎn)的值,我們?cè)僭囍Q他們的左右子樹,得到:8?/\?106?
/\
/\?119
75剛好就是規(guī)定的輸出。上面的分析印證了我們的直覺:在遍歷二元查找樹時(shí)每訪問到一個(gè)結(jié)點(diǎn),互換它的左右子樹。這種思緒用遞歸不難實(shí)現(xiàn),將遍歷二元查找樹的代碼稍作修改就可以了。參考代碼如下:///////////////////////////////////////////////////////////////////////?//MirroraBST(swaptheleftrightchildofeachnode)recursively
//theheadofBSTininitialcall
///////////////////////////////////////////////////////////////////////
voidMirrorRecursively(BSTree(cuò)Node*pNode)
{??if(!pNode)???return;
//swaptherightandleftchildsub-tree??BSTreeNode*pTemp=pNode->m_pLeft;??pNode->m_pLeft=pNode->m_pRight;? pNode->m_pRight=pTemp;???//mirrorleftchildsub-tree(cuò)ifnotnull? if(pNode->m_pLeft)
MirrorRecursively(pNode->m_pLeft);
??//mirrorrightchildsub-treeifnotnull
?if(pNode->m_pRight)?? MirrorRecursively(pNode->m_pRight);?}由于遞歸的本質(zhì)是編譯器生成了一個(gè)函數(shù)調(diào)用的棧,因此用循環(huán)來完畢同樣任務(wù)時(shí)最簡(jiǎn)樸的辦法就是用一個(gè)輔助棧來模擬遞歸。一方面我們把樹的頭結(jié)點(diǎn)放入棧中。在循環(huán)中,只要棧不為空,彈出棧的棧頂結(jié)點(diǎn),互換它的左右子樹。假如它有左子樹,把它的左子樹壓入棧中;假如它有右子樹,把它的右子樹壓入棧中。這樣在下次循環(huán)中就能互換它兒子結(jié)點(diǎn)的左右子樹了。參考代碼如下:///////////////////////////////////////////////////////////////////////?//MirroraBST(swaptheleftrightchildofeachnode)Iterat(yī)ively?//Input:pTreeHead:theheadofBST
///////////////////////////////////////////////////////////////////////
voidMirrorIteratively(BSTreeNode*pTreeHead)?{? if(?。餞reeHead)???return;
std::stack<BSTreeNode*>stackTreeNode;??stackTreeNode.push(pTreeHead);??while(stackTree(cuò)Node.size())??{? ?BSTreeNode*pNode=stackTreeNode.top();? ?stackTreeNode.pop();?? ?//swaptherightandleftchildsub-tree? ?BSTreeNode*pTemp=pNode->m_pLeft;
pNode->m_pLeft=pNode->m_pRight;?? pNode->m_pRight=pTemp;?
? //pushleftchildsub-treeintostackifnotnull? if(pNode->m_pLeft)
? ?stackTreeNode.push(pNode->m_pLeft);
??//pushrightchildsub-tree(cuò)intostackifnotnull
? if(pNode->m_pRight)
? stackTreeNode.push(pNode->m_pRight);??}
}程序員面試題精選100題(12)-從上往下遍歷二元樹HYPERLINK""\l"m=0&t=1&c=fks_"隊(duì)列2023-03-1921:17:03閱讀3798評(píng)論5
字號(hào):大中小
訂閱
題目:輸入一顆二元樹,從上往下按層打印樹的每個(gè)結(jié)點(diǎn),同一層中按照從左往右的順序打印。例如輸入8
/\?610?
/\/\
57911輸出861057911。分析:這曾是微軟的一道面試題。這道題實(shí)質(zhì)上是規(guī)定遍歷一棵二元樹,只但是不是我們熟悉的前序、中序或者后序遍歷。我們從樹的根結(jié)點(diǎn)開始分析。自然先應(yīng)當(dāng)打印根結(jié)點(diǎn)8,同時(shí)為了下次可以打印8的兩個(gè)子結(jié)點(diǎn),我們應(yīng)當(dāng)在遍歷到8時(shí)把子結(jié)點(diǎn)6和10保存到一個(gè)數(shù)據(jù)容器中?,F(xiàn)在數(shù)據(jù)容器中就有兩個(gè)元素6
和10了。按照從左往右的規(guī)定,我們先取出6訪問。打印6的同時(shí)要把6的兩個(gè)子結(jié)點(diǎn)5和7放入數(shù)據(jù)容器中,此時(shí)數(shù)據(jù)容器中有三個(gè)元素10、5和7。接下來我們應(yīng)當(dāng)從數(shù)據(jù)容器中取出結(jié)點(diǎn)10訪問了。注意10比5和7先放入容器,此時(shí)又比5和7先取出,就是我們通常說的先入先出。因此不難看出這個(gè)數(shù)據(jù)容器的類型應(yīng)當(dāng)是個(gè)隊(duì)列。既然已經(jīng)擬定數(shù)據(jù)容器是一個(gè)隊(duì)列,現(xiàn)在的問題變成怎么實(shí)現(xiàn)隊(duì)列了。事實(shí)上我們無需自己動(dòng)手實(shí)現(xiàn)一個(gè),由于STL已經(jīng)為我們實(shí)現(xiàn)了一個(gè)很好的deque(兩端都可以進(jìn)出的隊(duì)列),我們只需要拿過來用就可以了。我們知道樹是圖的一種特殊退化形式。同時(shí)假如對(duì)圖的深度優(yōu)先遍歷和廣度優(yōu)先遍歷有比較深刻的理解,將不難看出這種遍歷方式事實(shí)上是一種廣度優(yōu)先遍歷。因此這道題的本質(zhì)是在二元樹上實(shí)現(xiàn)廣度優(yōu)先遍歷。參考代碼:#include<deque>
#include<iostream>
usingnamespacestd;?structBTree(cuò)Node//anodeinthebinarytree
{
intm_nValue;//valueofnode
BTreeNode*m_pLeft;//leftchildofnode
?BTreeNode*m_pRight;//rightchildofnode
};
///////////////////////////////////////////////////////////////////////
//Printabinarytree(cuò)fromtopleveltobottomlevel?//Input:pTreeRoot-therootofbinarytree
///////////////////////////////////////////////////////////////////////
voidPrintFromTopToBottom(BTreeNode*pTreeRoot)?{
?if(!pTreeRoot)
? return;?? //getaemptyqueue? deque<BTree(cuò)Node*>dequeTreeNode;
??//inserttherootat(yī)thetailofqueue
dequeTree(cuò)Node.push_back(pTreeRoot);
? while(dequeTreeNode.size())
{
?//getanodefromtheheadofqueue???BTree(cuò)Node*pNode=dequeTreeNode.front();
??dequeTreeNode.pop_front();?
//printthenode
cout<<pNode->m_nValue<<'';????//printitsleftchildsub-tree(cuò)ifithas?? if(pNode->m_pLeft)????dequeTreeNode.push_back(pNode->m_pLeft);
? //printitsrightchildsub-treeifithas? ?if(pNode->m_pRight)??? dequeTreeNode.push_back(pNode->m_pRight);??}?}程序員面試題精選100題(13)-第一個(gè)只出現(xiàn)一次的字符HYPERLINK""\l"m=0&t=1&c=fks_"雜題2023-03-2512:03:22閱讀4450評(píng)論8
字號(hào):大中小
訂閱題目:n個(gè)數(shù)字(0,1,…,n-1)形成一個(gè)圓圈,從數(shù)字0開始,每次從這個(gè)圓圈中刪除第m個(gè)數(shù)字(第一個(gè)為當(dāng)前數(shù)字自身,第二個(gè)為當(dāng)前數(shù)字的下一個(gè)數(shù)字)。當(dāng)一個(gè)數(shù)字刪除后,從被刪除數(shù)字的下一個(gè)繼續(xù)刪除第m個(gè)數(shù)字。求出在這個(gè)圓圈中剩下的最后一個(gè)數(shù)字。分析:既然題目有一個(gè)數(shù)字圓圈,很自然的想法是我們用一個(gè)數(shù)據(jù)結(jié)構(gòu)來模擬這個(gè)圓圈。在常用的數(shù)據(jù)結(jié)構(gòu)中,我們很容易想到用環(huán)形列表。我們可以創(chuàng)建一個(gè)總共有m個(gè)數(shù)字的環(huán)形列表,然后每次從這個(gè)列表中刪除第m個(gè)元素。在參考代碼中,我們用STL中std::list來模擬這個(gè)環(huán)形列表。由于list并不是一個(gè)環(huán)形的結(jié)構(gòu),因此每次跌代器掃描到列表末尾的時(shí)候,要記得把跌代器移到列表的頭部。這樣就是按照一個(gè)圓圈的順序來遍歷這個(gè)列表了。這種思緒需要一個(gè)有n個(gè)結(jié)點(diǎn)的環(huán)形列表來模擬這個(gè)刪除的過程,因此內(nèi)存開銷為O(n)。并且這種方法每刪除一個(gè)數(shù)字需要m步運(yùn)算,總共有n個(gè)數(shù)字,因此總的時(shí)間復(fù)雜度是O(mn)。當(dāng)m和n都很大的時(shí)候,這種方法是很慢的。接下來我們?cè)囍鴱臄?shù)學(xué)上分析出一些規(guī)律。一方面定義最初的n個(gè)數(shù)字(0,1,…,n-1)中最后剩下的數(shù)字是關(guān)于n和m的方程為f(n,m)。在這n個(gè)數(shù)字中,第一個(gè)被刪除的數(shù)字是m%n-1,為簡(jiǎn)樸起見記為k。那么刪除k之后的剩下n-1的數(shù)字為0,1,…,k-1,k+1,…,n-1,并且下一個(gè)開始計(jì)數(shù)的數(shù)字是k+1。相稱于在剩下的序列中,k+1排到最前面,從而形成序列k+1,…,n-1,0,…k-1。該序列最后剩下的數(shù)字也應(yīng)當(dāng)是關(guān)于n和m的函數(shù)。由于這個(gè)序列的規(guī)律和前面最初的序列不同樣(最初的序列是從0開始的連續(xù)序列),因此該函數(shù)不同于前面函數(shù),記為f’(n-1,m)。最初序列最后剩下的數(shù)字f(n,m)一定是剩下序列的最后剩下數(shù)字f’(n-1,m),所以f(n,m)=f’(n-1,m)。接下來我們把剩下的的這n-1個(gè)數(shù)字的序列k+1,…,n-1,0,…k-1作一個(gè)映射,映射的結(jié)果是形成一個(gè)從0到n-2的序列:k+1->0
k+2->1?…
n-1->n-k-2
0->n-k-1
…
k-1->n-2把映射定義為p,則p(x)=(x-k-1)%n,即假如映射前的數(shù)字是x,則映射后的數(shù)字是(x-k-1)%n。相應(yīng)的逆映射是p-1(x)=(x+k+1)%n。由于映射之后的序列和最初的序列有同樣的形式,都是從0開始的連續(xù)序列,因此仍然可以用函數(shù)f來表達(dá),記為f(n-1,m)。根據(jù)我們的映射規(guī)則,映射之前的序列最后剩下的數(shù)字f’(n-1,m)=p-1[f(n-1,m)]=[f(n-1,m)+k+1]%n。把k=m%n-1代入得到f(n,m)=f’(n-1,m)=[f(n-1,m)+m]%n。通過上面復(fù)雜的分析,我們終于找到一個(gè)遞歸的公式。要得到n個(gè)數(shù)字的序列的最后剩下的數(shù)字,只需要得到n-1個(gè)數(shù)字的序列的最后剩下的數(shù)字,并可以依此類推。當(dāng)n=1時(shí),也就是序列中開始只有一個(gè)數(shù)字0,那么很顯然最后剩下的數(shù)字就是0。我們把這種關(guān)系表達(dá)為:0n=1?f(n,m)={?[f(n-1,m)+m]%nn>1盡管得到這個(gè)公式的分析過程非常復(fù)雜,但它用遞歸或者循環(huán)都很容易實(shí)現(xiàn)。最重要的是,這是一種時(shí)間復(fù)雜度為O(n),空間復(fù)雜度為O(1)的方法,因此無論在時(shí)間上還是空間上都優(yōu)于前面的思緒。思緒一的參考代碼:///////////////////////////////////////////////////////////////////////
//nintegers(0,1,...n-1)formacircle.Removethemthfrom
//thecircleateverytime.Findthelastnumberremaining
//Input:n-thenumberofintegersinthecircleinitially?//m-removethemthnumberateverytime?//Output:thelastnumberremainingwhentheinputisvalid,
//otherwise-1
///////////////////////////////////////////////////////////////////////?intLastRemaining_Solution1(unsignedintn,unsignedintm)
{??//invalidinput
?if(n<1||m<1)? return-1;
unsignedinti=0;?? //initiatealistwithnintegers(0,1,...n-1)
list<int>integers;
for(i=0;i<n;++i)?? integers.push_back(i);?
?list<int>::iterat(yī)orcurinteger=integers.begin();
?while(integers.size()>1)? {? //findthemthinteger.Notethatstd::listisnotacircle?? //soweshouldhandleitmanually
??for(inti=1;i<m;++i)???{
? curinteger++;
? ?if(curinteger==integers.end())? ? curinteger=integers.begin();
}?? //removethemthinteger.Notethatstd::listisnotacircle? //sowesh
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 九年級(jí)體育 韻律體操與舞蹈 任選教材教案3
- 安徽省滁州二中高中信息技術(shù)《3.1文本信息的加工與表達(dá)(2)》教案 新人教版必修
- 2024-2025學(xué)年七年級(jí)生物上冊(cè) 3.1.1 藻類、苔蘚、蕨類植物教案 (新版)新人教版
- 2024年學(xué)校前臺(tái)工作人員雇傭合同
- 2024年工程合作方共同承包協(xié)議
- 2024年企業(yè)采購戰(zhàn)略合作項(xiàng)目的價(jià)格談判合同
- 2024年城市軌道交通信號(hào)系統(tǒng)升級(jí)協(xié)議
- 2024年城市公共交通運(yùn)營(yíng)合同標(biāo)的與服務(wù)區(qū)域
- 2024雙方關(guān)于共同研發(fā)新能源車輛充電設(shè)施合同
- 2024年定制毛坯商鋪?zhàn)赓U合同模板
- 小學(xué)二年級(jí)上冊(cè)語文部編版課件 紙船和風(fēng)箏(生字講解)
- 紅色消防安全知識(shí)宣傳培訓(xùn)課件PPT模板
- 果蔬機(jī)械冷藏課件2
- 拼音復(fù)習(xí)-拼音轉(zhuǎn)盤課件
- 項(xiàng)目進(jìn)度管理培訓(xùn)(-)課件
- 高考語文 如何讀懂詩歌 課件(32張PPT)
- 中壓交聯(lián)電纜電纜正、負(fù)和零序計(jì)算
- 3C戰(zhàn)略三角模型
- 高標(biāo)準(zhǔn)農(nóng)田建設(shè)示范工程質(zhì)量管理體系與措施
- 學(xué)生頂崗實(shí)習(xí)安全教育課件
- 公司組織架構(gòu)圖模板課件
評(píng)論
0/150
提交評(píng)論