版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
程序員面試題精選100題(10)-在排序數(shù)組中查找和為給定值的兩個數(shù)字HYPERLINK""\l"m=0&t=1&c=fks_"數(shù)組2023-03-1415:25:01閱讀4663評論15
字號:大中小
訂閱題目:輸入一個已經(jīng)按升序排序過的數(shù)組和一個數(shù)字,在數(shù)組中查找兩個數(shù),使得它們的和正好是輸入的那個數(shù)字。規(guī)定期間復(fù)雜度是O(n)。假如有多對數(shù)字的和等于輸入的數(shù)字,輸出任意一對即可。例如輸入數(shù)組1、2、4、7、11、15和數(shù)字15。由于4+11=15,因此輸出4和11。分析:假如我們不考慮時間復(fù)雜度,最簡樸想法的莫過去先在數(shù)組中固定一個數(shù)字,再依次判斷數(shù)組中剩下的n-1個數(shù)字與它的和是不是等于輸入的數(shù)字??上н@種思緒需要的時間復(fù)雜度是O(n2)。我們假設(shè)現(xiàn)在隨便在數(shù)組中找到兩個數(shù)。假如它們的和等于輸入的數(shù)字,那太好了,我們找到了要找的兩個數(shù)字;假如小于輸入的數(shù)字呢?我們希望兩個數(shù)字的和再大一點。由于數(shù)組已經(jīng)排好序了,我們是不是可以把較小的數(shù)字的往后面移動一個數(shù)字?由于排在后面的數(shù)字要大一些,那么兩個數(shù)字的和也要大一些,就有也許等于輸入的數(shù)字了;同樣,當(dāng)兩個數(shù)字的和大于輸入的數(shù)字的時候,我們把較大的數(shù)字往前移動,由于排在數(shù)組前面的數(shù)字要小一些,它們的和就有也許等于輸入的數(shù)字了。我們把前面的思緒整理一下:最初我們找到數(shù)組的第一個數(shù)字和最后一個數(shù)字。當(dāng)兩個數(shù)字的和大于輸入的數(shù)字時,把較大的數(shù)字往前移動;當(dāng)兩個數(shù)字的和小于數(shù)字時,把較小的數(shù)字往后移動;當(dāng)相等時,打完收工。這樣掃描的順序是從數(shù)組的兩端向數(shù)組的中間掃描。問題是這樣的思緒是不是對的的呢?這需要嚴(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ù)字程序員面試題精選100題(11)-求二元查找樹的鏡像HYPERLINK""\l"m=0&t=1&c=fks_"樹2023-03-1509:36:33閱讀3906評論9
字號:大中小
訂閱題目:輸入一顆二元查找樹,將該樹轉(zhuǎn)換為它的鏡像,即在轉(zhuǎn)換后的二元查找樹中,左子樹的結(jié)點都大于右子樹的結(jié)點。用遞歸和循環(huán)兩種方法完畢樹的鏡像轉(zhuǎn)換。例如輸入:8?/\?610?
/\/\
57911輸出:8?/\
106?
/\
/\
119
75定義二元查找樹的結(jié)點為:structBSTreeNode//anodeinthebinarysearchtree(BST)?{? intm_nValue;//valueofnode
?BSTreeNode*m_pLeft;//leftchildofnode??BSTreeNode*m_pRight;//rightchildofnode?};分析:盡管我們也許一下子不能理解鏡像是什么意思,但上面的例子給我們的直觀感覺,就是互換結(jié)點的左右子樹。我們試著在遍歷例子中的二元查找樹的同時來互換每個結(jié)點的左右子樹。遍歷時一方面訪問頭結(jié)點8,我們互換它的左右子樹得到:8?/\?106?
/\/\?91157我們發(fā)現(xiàn)兩個結(jié)點6和10的左右子樹仍然是左結(jié)點的值小于右結(jié)點的值,我們再試著互換他們的左右子樹,得到:8?/\?106?
/\
/\?119
75剛好就是規(guī)定的輸出。上面的分析印證了我們的直覺:在遍歷二元查找樹時每訪問到一個結(jié)點,互換它的左右子樹。這種思緒用遞歸不難實現(xiàn),將遍歷二元查找樹的代碼稍作修改就可以了。參考代碼如下:///////////////////////////////////////////////////////////////////////?//MirroraBST(swaptheleftrightchildofeachnode)recursively
//theheadofBSTininitialcall
///////////////////////////////////////////////////////////////////////
voidMirrorRecursively(BSTreeNode*pNode)
{??if(!pNode)???return;
//swaptherightandleftchildsub-tree??BSTreeNode*pTemp=pNode->m_pLeft;??pNode->m_pLeft=pNode->m_pRight;? pNode->m_pRight=pTemp;???//mirrorleftchildsub-treeifnotnull? if(pNode->m_pLeft)
MirrorRecursively(pNode->m_pLeft);
??//mirrorrightchildsub-treeifnotnull
?if(pNode->m_pRight)?? MirrorRecursively(pNode->m_pRight);?}由于遞歸的本質(zhì)是編譯器生成了一個函數(shù)調(diào)用的棧,因此用循環(huán)來完畢同樣任務(wù)時最簡樸的辦法就是用一個輔助棧來模擬遞歸。一方面我們把樹的頭結(jié)點放入棧中。在循環(huán)中,只要棧不為空,彈出棧的棧頂結(jié)點,互換它的左右子樹。假如它有左子樹,把它的左子樹壓入棧中;假如它有右子樹,把它的右子樹壓入棧中。這樣在下次循環(huán)中就能互換它兒子結(jié)點的左右子樹了。參考代碼如下:///////////////////////////////////////////////////////////////////////?//MirroraBST(swaptheleftrightchildofeachnode)Iterat(yī)ively?//Input:pTreeHead:theheadofBST
///////////////////////////////////////////////////////////////////////
voidMirrorIteratively(BSTreeNode*pTreeHead)?{? if(?。餞reeHead)???return;
std::stack<BSTreeNode*>stackTreeNode;??stackTreeNode.push(pTreeHead);??while(stackTreeNode.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-treeintostackifnotnull
? if(pNode->m_pRight)
? stackTreeNode.push(pNode->m_pRight);??}
}程序員面試題精選100題(12)-從上往下遍歷二元樹HYPERLINK""\l"m=0&t=1&c=fks_"隊列2023-03-1921:17:03閱讀3798評論5
字號:大中小
訂閱
題目:輸入一顆二元樹,從上往下按層打印樹的每個結(jié)點,同一層中按照從左往右的順序打印。例如輸入8
/\?610?
/\/\
57911輸出861057911。分析:這曾是微軟的一道面試題。這道題實質(zhì)上是規(guī)定遍歷一棵二元樹,只但是不是我們熟悉的前序、中序或者后序遍歷。我們從樹的根結(jié)點開始分析。自然先應(yīng)當(dāng)打印根結(jié)點8,同時為了下次可以打印8的兩個子結(jié)點,我們應(yīng)當(dāng)在遍歷到8時把子結(jié)點6和10保存到一個數(shù)據(jù)容器中?,F(xiàn)在數(shù)據(jù)容器中就有兩個元素6
和10了。按照從左往右的規(guī)定,我們先取出6訪問。打印6的同時要把6的兩個子結(jié)點5和7放入數(shù)據(jù)容器中,此時數(shù)據(jù)容器中有三個元素10、5和7。接下來我們應(yīng)當(dāng)從數(shù)據(jù)容器中取出結(jié)點10訪問了。注意10比5和7先放入容器,此時又比5和7先取出,就是我們通常說的先入先出。因此不難看出這個數(shù)據(jù)容器的類型應(yīng)當(dāng)是個隊列。既然已經(jīng)擬定數(shù)據(jù)容器是一個隊列,現(xiàn)在的問題變成怎么實現(xiàn)隊列了。事實上我們無需自己動手實現(xiàn)一個,由于STL已經(jīng)為我們實現(xiàn)了一個很好的deque(兩端都可以進(jìn)出的隊列),我們只需要拿過來用就可以了。我們知道樹是圖的一種特殊退化形式。同時假如對圖的深度優(yōu)先遍歷和廣度優(yōu)先遍歷有比較深刻的理解,將不難看出這種遍歷方式事實上是一種廣度優(yōu)先遍歷。因此這道題的本質(zhì)是在二元樹上實現(xiàn)廣度優(yōu)先遍歷。參考代碼:#include<deque>
#include<iostream>
usingnamespacestd;?structBTreeNode//anodeinthebinarytree
{
intm_nValue;//valueofnode
BTreeNode*m_pLeft;//leftchildofnode
?BTreeNode*m_pRight;//rightchildofnode
};
///////////////////////////////////////////////////////////////////////
//Printabinarytreefromtopleveltobottomlevel?//Input:pTreeRoot-therootofbinarytree
///////////////////////////////////////////////////////////////////////
voidPrintFromTopToBottom(BTreeNode*pTreeRoot)?{
?if(!pTreeRoot)
? return;?? //getaemptyqueue? deque<BTreeNode*>dequeTreeNode;
??//inserttherootat(yī)thetailofqueue
dequeTreeNode.push_back(pTreeRoot);
? while(dequeTreeNode.size())
{
?//getanodefromtheheadofqueue???BTreeNode*pNode=dequeTreeNode.front();
??dequeTreeNode.pop_front();?
//printthenode
cout<<pNode->m_nValue<<'';????//printitsleftchildsub-treeifithas?? if(pNode->m_pLeft)????dequeTreeNode.push_back(pNode->m_pLeft);
? //printitsrightchildsub-treeifithas? ?if(pNode->m_pRight)??? dequeTreeNode.push_back(pNode->m_pRight);??}?}程序員面試題精選100題(13)-第一個只出現(xiàn)一次的字符HYPERLINK""\l"m=0&t=1&c=fks_"雜題2023-03-2512:03:22閱讀4450評論8
字號:大中小
訂閱題目:n個數(shù)字(0,1,…,n-1)形成一個圓圈,從數(shù)字0開始,每次從這個圓圈中刪除第m個數(shù)字(第一個為當(dāng)前數(shù)字自身,第二個為當(dāng)前數(shù)字的下一個數(shù)字)。當(dāng)一個數(shù)字刪除后,從被刪除數(shù)字的下一個繼續(xù)刪除第m個數(shù)字。求出在這個圓圈中剩下的最后一個數(shù)字。分析:既然題目有一個數(shù)字圓圈,很自然的想法是我們用一個數(shù)據(jù)結(jié)構(gòu)來模擬這個圓圈。在常用的數(shù)據(jù)結(jié)構(gòu)中,我們很容易想到用環(huán)形列表。我們可以創(chuàng)建一個總共有m個數(shù)字的環(huán)形列表,然后每次從這個列表中刪除第m個元素。在參考代碼中,我們用STL中std::list來模擬這個環(huán)形列表。由于list并不是一個環(huán)形的結(jié)構(gòu),因此每次跌代器掃描到列表末尾的時候,要記得把跌代器移到列表的頭部。這樣就是按照一個圓圈的順序來遍歷這個列表了。這種思緒需要一個有n個結(jié)點的環(huán)形列表來模擬這個刪除的過程,因此內(nèi)存開銷為O(n)。并且這種方法每刪除一個數(shù)字需要m步運算,總共有n個數(shù)字,因此總的時間復(fù)雜度是O(mn)。當(dāng)m和n都很大的時候,這種方法是很慢的。接下來我們試著從數(shù)學(xué)上分析出一些規(guī)律。一方面定義最初的n個數(shù)字(0,1,…,n-1)中最后剩下的數(shù)字是關(guān)于n和m的方程為f(n,m)。在這n個數(shù)字中,第一個被刪除的數(shù)字是m%n-1,為簡樸起見記為k。那么刪除k之后的剩下n-1的數(shù)字為0,1,…,k-1,k+1,…,n-1,并且下一個開始計數(shù)的數(shù)字是k+1。相稱于在剩下的序列中,k+1排到最前面,從而形成序列k+1,…,n-1,0,…k-1。該序列最后剩下的數(shù)字也應(yīng)當(dāng)是關(guān)于n和m的函數(shù)。由于這個序列的規(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個數(shù)字的序列k+1,…,n-1,0,…k-1作一個映射,映射的結(jié)果是形成一個從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ù)雜的分析,我們終于找到一個遞歸的公式。要得到n個數(shù)字的序列的最后剩下的數(shù)字,只需要得到n-1個數(shù)字的序列的最后剩下的數(shù)字,并可以依此類推。當(dāng)n=1時,也就是序列中開始只有一個數(shù)字0,那么很顯然最后剩下的數(shù)字就是0。我們把這種關(guān)系表達(dá)為:0n=1?f(n,m)={?[f(n-1,m)+m]%nn>1盡管得到這個公式的分析過程非常復(fù)雜,但它用遞歸或者循環(huán)都很容易實現(xiàn)。最重要的是,這是一種時間復(fù)雜度為O(n),空間復(fù)雜度為O(1)的方法,因此無論在時間上還是空間上都優(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等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工作總結(jié)之服裝設(shè)計助理實習(xí)總結(jié)
- 工地上工程進(jìn)展情況報告-建筑實操
- 2024年柔印CTP項目資金需求報告
- 銀行合規(guī)管理制度修訂
- 酒店餐飲服務(wù)規(guī)范及衛(wèi)生要求制度
- 支教社會實踐報告15篇
- 高中期中考試后總結(jié)(33篇)
- 黃山導(dǎo)游詞1500字(31篇)
- 2024智能充電樁技術(shù)規(guī)范
- 《輸煤除塵器培訓(xùn)》課件
- 引導(dǎo)孩子學(xué)會適應(yīng)與調(diào)適
- 醫(yī)院藥品目錄(很好的)
- 廈門大學(xué)2023年826物理化學(xué)考研真題(含答案)
- 安徽省縣中聯(lián)盟2023-2024學(xué)年高二上學(xué)期12月聯(lián)考數(shù)學(xué)試題
- 本量利分析和差量分析法的應(yīng)用課件
- 國外醫(yī)學(xué)教育模式比較與我國醫(yī)學(xué)教育學(xué)制改革
- 軍事知識常識小學(xué)生
- 班級管理課件:班級管理評價
- 護(hù)理搶救質(zhì)控匯報課件
- 初中數(shù)學(xué)思想方法導(dǎo)引
- 2023年政府采購評審專家入庫考試模擬題型及答案
評論
0/150
提交評論