版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
程序員編程藝術(shù)第二十八~二十九章:最大連續(xù)乘積子串、字符串編輯距離第二十八~二十九章:最大連續(xù)乘積子串、字符串編輯距離前言時間轉(zhuǎn)瞬即逝,一轉(zhuǎn)眼,又有4個多月沒來更新blog了,過去4個月都在干啥呢?對的,今2023年元旦和朋友一起搭了個方便朋友們找工作的編程面試算法論壇:為學(xué)論壇。最近則在負(fù)責(zé)一款在線編程挑戰(zhàn)平臺--英雄會的產(chǎn)品運營,當(dāng)然拉,雖說是產(chǎn)品運營,事實上身兼“數(shù)職”:出題審題,寫代碼測試一個不落下。最近跟百度的幾個朋友線下閑聊,聽他們說,百度校招群內(nèi)的不少朋友在找工作的時候都看過我的blog,一聽當(dāng)即便激起了自己重寫更新此blog的欲望,恰巧眼下陽春三月(雖說已是3月,奇妙的是,前兩天北京還下了一場大雪),又到了找工作的季節(jié)(相對于每年的9月份來說,3月則是一個小高潮),那就從繼續(xù)更新專為找工作準(zhǔn)備筆試面試的程序員編程藝術(shù)開始吧。本文講兩個問題,第二十八章、最大連續(xù)乘積子串,第二十九章、字符串編輯距離,這兩個問題皆是各大IT公司最喜歡出的筆試面試題,比如說前者是小米2023年校招筆試原題,而后者則更是反復(fù)出現(xiàn),如去年9月26日百度一二面試題,10月9日騰訊面試題第1小題,10月13日百度2023校招北京站筆試題第二大道題第3小題,及去年10月15日2023年Google校招筆試最后一道大題。OK,歡迎朋友們在本文下參與討論,假如用Java/C#的朋友想在線編譯自己的代碼,可以上英雄會提交你的代碼,有任何問題,歡迎隨時不吝批評或指正,感謝。第二十九章、最大連續(xù)乘積子串題目描述:給一個浮點數(shù)序列,取最大乘積連續(xù)子串的值,例如-2.5,4,0,3,0.5,8,-1,則取出的最大乘積連續(xù)子串為3,0.5,8。也就是說,上述數(shù)組中,30.58這3個數(shù)的乘積3*0.5*8=12是最大的,并且是連續(xù)的。提醒:此最大乘積連續(xù)子串與最大乘積子序列不同,請勿混淆,前者子串規(guī)定連續(xù),后者子序列不規(guī)定連續(xù)。也就是說:最長公共子串(LongestCommonSubstring)和最長公共子序列(LongestCommonSubsequence,LCS)的區(qū)別:子串(Substring)是串的一個連續(xù)的部分,子序列(Subsequence)則是從不改變序列的順序,而從序列中去掉任意的元素而獲得的新序列;更簡略地說,前者(子串)的字符的位置必須連續(xù),后者(子序列LCS)則不必。比如字符串a(chǎn)cdfg同akdfc的最長公共子串為df,而他們的最長公共子序列是adf。LCS可以使用動態(tài)規(guī)劃法解決。解答:解法一、兩個for循環(huán)直接輪詢或許,讀者初看此題,自然會想到最大乘積子序列問題類似于最大子數(shù)組和問題:,最簡樸粗暴的方式便是用鏈兩個for循環(huán)直接輪詢。for(inti=0;i<num;i++){doublex=arrs[i];for(intj=i+1;j<num;j++){x*=arrs[j];if(x>max){max=x;start=arrs[i];end=arrs[j];}}解法二、雖說類似于最大子數(shù)組和問題,可以用兩個for循環(huán)直接輪詢搞定,但事實上具體解決起來諸多不同,為什么呢,由于乘積子序列中有正有負(fù)也還也許有0。我們可以把問題簡化成這樣:數(shù)組中找一個子序列,使得它的乘積最大;同時找一個子序列,使得它的乘積最小(負(fù)數(shù)的情況)。由于雖然我們只要一個最大積,但由于負(fù)數(shù)的存在,我們同時找這兩個乘積做起來反而方便。也就是說,不僅記錄最大乘積,也要記錄最小乘積。So,我們讓maxCurrent表達當(dāng)前最大乘積的candidate,minCurrent反之,表達當(dāng)前最小乘積的candidate(用candidat(yī)e這個詞是由于只是也許成為新一輪的最大/最小乘積),而maxProduct則記錄到目前為止所有最大乘積candidat(yī)es的最大值。由于空集的乘積定義為1,在搜索數(shù)組前,maxCurrent,minCurrent,maxProduct都賦為1。假設(shè)在任何時刻你已有了maxCurrent和minCurrent這兩個最大/最小乘積的candidates,新讀入數(shù)組的元素x(i)后,新的最大乘積candidate只也許是maxCurrent或者minCurrent與x(i)的乘積中的較大者,假如x(i)<0導(dǎo)致maxCurrent<minCurrent,需要互換這兩個candidat(yī)es的值。當(dāng)任何時候maxCurrent<1,由于1(空集)是比maxCurrent更好的candidate,所以更新maxCurrent為1,類似的可以更新minCurrent。任何時候maxCurrent假如比最佳的maxProduct大,更新maxProduct。具體代碼如下:template<typenameComparable>Comparablemaxprod(constvector<Comparable>&v){inti;ComparablemaxProduct=1;ComparableminProduct=1;ComparablemaxCurrent=1;ComparableminCurrent=1;//Comparablet;for(i=0;i<v.size();i++){maxCurrent*=v[i];minCurrent*=v[i];if(maxCurrent>maxProduct)maxProduct=maxCurrent;if(minCurrent>maxProduct)maxProduct=minCurrent;if(maxCurrent<minProduct)minProduct=maxCurrent;if(minCurrent<minProduct)minProduct=minCurrent;if(minCurrent>maxCurrent)swap(maxCurrent,minCurrent);if(maxCurrent<1)maxCurrent=1;//if(minCurrent>1)//minCurrent=1;}returnmaxProduct;}解法三、本題除了上述類似最大子數(shù)組和的解法,也可以直接用動態(tài)規(guī)劃求解(其實,上述的解法一本質(zhì)上也是動態(tài)規(guī)劃,只是解題所表現(xiàn)出來的具體形式與接下來的解法二不同罷了。這個不同就在于下面的解法二會寫出動態(tài)規(guī)劃問題中經(jīng)典常見的狀態(tài)轉(zhuǎn)移方程,而解法一是直接求解)。具體解法如下:假設(shè)數(shù)組為a[],直接運用動歸來求解,考慮到也許存在負(fù)數(shù)的情況,我們用Max來表達以a結(jié)尾的最大連續(xù)子串的乘積值,用Min表達以a結(jié)尾的最小的子串的乘積值,那么狀態(tài)轉(zhuǎn)移方程為:Max=max{a,Max[i-1]*a,Min[i-1]*a};Min=min{a,Max[i-1]*a,Min[i-1]*a};初始狀態(tài)為Max[1]=Min[1]=a[1]。代碼如下:/*給定一個整數(shù)數(shù)組,有正有負(fù)數(shù),0,正數(shù)組成,數(shù)組下標(biāo)從1算起求最大連續(xù)子序列乘積,并輸出這個序列,假如最大子序列乘積為負(fù)數(shù),那么就輸出-1用Max[i]表達以a[i]結(jié)尾乘積最大的連續(xù)子序列用Min[i]表達以a[i]結(jié)尾乘積最小的連續(xù)子序列由于有復(fù)數(shù),所以保存這個是必須的*/voidlongest_multiple(int*a,intn){int*Min=newint[n+1]();int*Max=newint[n+1]();int*p=newint[n+1]();//初始化for(inti=0;i<=n;i++){p[i]=-1;}Min[1]=a[1];Max[1]=a[1];intmax_val=Max[1];for(inti=2;i<=n;i++){Max[i]=max(Max[i-1]*a[i],Min[i-1]*a[i],a[i]);Min[i]=min(Max[i-1]*a[i],Min[i-1]*a[i],a[i]);if(max_val<Max[i])max_val=Max[i];}if(max_val<0)printf("%d",-1);elseprintf("%d",max_val);//內(nèi)存釋放delete[]Max;delete[]Min;}提煉簡化下上面的核心代碼為:doublefunc(double*a,constintn){double*maxA=newdouble[n];double*minA=newdouble[n];maxA[0]=minA(yù)[0]=a[0];doublevalue=maxA[0];for(inti=1;i<n;++i){maxA[i]=max(max(a[i],maxA[i-1]*a[i]),minA[i-1]*a[i]);minA[i]=min(min(a[i],maxA[i-1]*a[i]),minA[i-1]*a[i]);value=max(value,maxA[i]);}returnvalue;}變種此外,此題尚有此外的一個變種形式,即給定一個長度為N的整數(shù)數(shù)組,只允許用乘法,不能用除法,計算任意(N-1)個數(shù)的組合中乘積最大的一組,并寫出算法的時間復(fù)雜度。我們可以把所有也許的(N-1)個數(shù)的組合找出來,分別計算它們的乘積,并比較大小。由于總共有N個(N-1)個數(shù)的組合,總的時間復(fù)雜度為O(N2),顯然這不是最佳的解法。OK,以下解答來自編程之美解法1解法2此外,還可以通過度析,進一步減少解答問題的計算量。假設(shè)N個整數(shù)的乘積為P,針對P的正負(fù)性進行如下分析(其中,AN-1表達N-1個數(shù)的組合,PN-1表達N-1個數(shù)的組合的乘積)。1.P為0那么,數(shù)組中至少包具有一個0。假設(shè)除去一個0之外,其他N-1個數(shù)的乘積為Q,根據(jù)Q的正負(fù)性進行討論:Q為0說明數(shù)組中至少有兩個0,那么N-1個數(shù)的乘積只能為0,返回0;Q為正數(shù)返回Q,由于假如以0替換此時AN-1中的任一個數(shù),所得到的PN-1為0,必然小于Q;Q為負(fù)數(shù)假如以0替換此時AN-1中的任一個數(shù),所得到的PN-1為0,大于Q,乘積最大值為0。2.P為負(fù)數(shù)根據(jù)“負(fù)負(fù)得正”的乘法性質(zhì),自然想到從N個整數(shù)中去掉一個負(fù)數(shù),使得PN-1為一個正數(shù)。而要使這個正數(shù)最大,這個被去掉的負(fù)數(shù)的絕對值必須是數(shù)組中最小的。我們只需要掃描一遍數(shù)組,把絕對值最小的負(fù)數(shù)給去掉就可以了。3.P為正數(shù)類似地,假如數(shù)組中存在正數(shù)值,那么應(yīng)當(dāng)去掉最小的正數(shù)值,否則去掉絕對值最大的負(fù)數(shù)值。上面的解法采用了直接求N個整數(shù)的乘積P,進而判斷P的正負(fù)性的辦法,但是直接求乘積在編譯環(huán)境下往往會有溢出的危險(這也就是本題規(guī)定不使用除法的潛在用意),事實上可做一個小的轉(zhuǎn)變,不需要直接求乘積,而是求出數(shù)組中正數(shù)(+)、負(fù)數(shù)(-)和0的個數(shù),從而判斷P的正負(fù)性,其余部分與以上面的解法相同。在時間復(fù)雜度方面,由于只需要遍歷數(shù)組一次,在遍歷數(shù)組的同時就可得到數(shù)組中正數(shù)(+)、負(fù)數(shù)(-)和0的個數(shù),以及數(shù)組中絕對值最小的正數(shù)和負(fù)數(shù),時間復(fù)雜度為O(N)。第二十九章、字符串編輯距離題目描述:給定一個源串和目的串,可以對源串進行如下操作:1.在給定位置上插入一個字符2.替換任意字符3.刪除任意字符寫一個程序,返回最小操作數(shù),使得對源串進行這些操作后等于目的串,源串和目的串的長度都小于2023。提醒:上文前言中已經(jīng)說過了,此題反復(fù)出現(xiàn),最近考的最多的是百度和Google的筆試面試經(jīng)??疾?。下圖則是2023年Google的校招試題原景重現(xiàn):解答:解法一、此題跟上面的最大連續(xù)乘積子串類似,常見的思緒是動態(tài)規(guī)劃,下面是簡樸的DP狀態(tài)方程://動態(tài)規(guī)劃://f[i,j]表達s[0...i]與t[0...j]的最小編輯距離。f[i,j]=min{f[i-1,j]+1,f[i,j-1]+1,f[i-1,j-1]+(s[i]==t[j]?0:1)}//分別表達:添加1個,刪除1個,替換1個(相同就不用替換)。解法二、類似上述問題類似于編程之美上的下述一題「以下內(nèi)容摘自編程之美第3.3節(jié)」:許多程序會大量使用字符串。對于不同的字符串,我們希望可以有辦法判斷其相似限度。我們定義了一套操作方法來把兩個不相同的字符串變得相同,具體的操作方法為:修改一個字符(如把“a”替換為“b”);增長一個字符(如把“abdd”變?yōu)椤癮ebdd”);刪除一個字符(如把“travelling”變?yōu)椤埃簦颍幔鰁ling”)。比如,對于“abcdefg”和“abcdef”兩個字符串來說,我們認(rèn)為可以通過增長/減少一個“g”的方式來達成目的。上面的兩種方案,都僅需要一次操作。把這個操作所需要的次數(shù)定義為兩個字符串的距離,而相似度等于“距離+1”的倒數(shù)。也就是說,“abcdefg”和“abcdef”的距離為1,相似度為1/2=0.5。給定任意兩個字符串,你是否能寫出一個算法來計算出它們的相似度呢?這樣,不久就可以完畢一個遞歸程序,如下所示:IntCalculateStringDistance(stringstrA,intpABegin,intpAEnd,stringstrB,intpBBegin,intpBEnd){if(pABegin>pAEnd){if(pBBegin>pBEnd)return0;elsereturnpB(yǎng)End–pBBegin+1;}if(pBBegin>pBEnd){if(pABegin>pAEnd)return0;elsereturnpAEnd–pABegin+1;}if(strA[pAB
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 國慶升旗講話稿范文(5篇)
- 信息素在性別識別中的作用-洞察分析
- 藥物支架在肝癌治療中的作用-洞察分析
- 疫苗接種倫理與法規(guī)探討-洞察分析
- 油氣行業(yè)智能化升級-洞察分析
- 云平臺互操作性研究-洞察分析
- 污染土壤生物修復(fù)技術(shù)-洞察分析
- 鄉(xiāng)村文化景觀旅游開發(fā)-洞察分析
- 宇宙射線多信使天文學(xué)-洞察分析
- 網(wǎng)絡(luò)謠言傳播機制研究-洞察分析
- 廣東省佛山市南海區(qū)·三水區(qū)2023-2024學(xué)年七年級上學(xué)期期末數(shù)學(xué)試題
- 減肥及代謝手術(shù)課件
- 2025年中國社區(qū)團購行業(yè)發(fā)展環(huán)境、運行態(tài)勢及投資前景分析報告(智研咨詢發(fā)布)
- 24秋二年級上冊語文期末復(fù)習(xí)21天沖刺計劃(每日5道題)
- 2024年度健康醫(yī)療服務(wù)合同平安好醫(yī)生(2024版)3篇
- 《中國傳統(tǒng)民居建筑》課件
- JJF 2163-2024漆膜劃格器校準(zhǔn)規(guī)范
- 肺炎支原體肺炎-4
- 【教案】Unit4+Section+B+(1a-2b)+教學(xué)設(shè)計人教版(2024)七年級英語上冊++
- 好作文的開頭和結(jié)尾公開課獲獎?wù)n件省賽課一等獎?wù)n件
- 替莫唑胺在小細胞肺癌中的應(yīng)用
評論
0/150
提交評論