使用Python
確定包含范圍內(nèi)不包含壞數(shù)字的最長整數(shù)段。是Python的新手。 Hackerrank中有一個問題。給定一個壞數(shù)字?jǐn)?shù)組和一個整數(shù)范圍,如何確定包含范圍內(nèi)不包含壞數(shù)字的最
解答動態(tài)
PEP 8 Python代碼的樣式指南列出了許多建議結(jié)束語:變量和;函數(shù)應(yīng)該是snake\u case逗號后面應(yīng)該跟一個空格二進(jìn)制運(yùn)算符應(yīng)該被一個空格包圍(例如,l==r而不是l==r,r+1而不是r+1) 有些函數(shù)/變量名可能是由編碼挑戰(zhàn)指定給您的,但是對于所有其他的你應(yīng)該遵循PEP 8約定。
OptimizationsLoop range for i in range(l,r+1):
假設(shè)你的范圍是1到\$10^9\$,如果循環(huán)中的代碼每次迭代花費(fèi)10納秒以上,這個循環(huán)將花費(fèi)10秒以上。這對翻譯語言要求很高。如果可以刪除該循環(huán),您會做得更好。
請稍后對此進(jìn)行詳細(xì)說明。
Counting-vs-existence if壞數(shù)字。計(jì)數(shù)(i) ==0:
您正在搜索錯誤數(shù)字列表,對列表中值i的出現(xiàn)次數(shù)進(jìn)行計(jì)數(shù)。
badNumbers包含不同的元素
由于badNumbers包含唯一的元素,因此計(jì)數(shù)將為0或1。更重要的是,一旦我們找到第一個匹配項(xiàng),我們就可以停止計(jì)數(shù),即使保證了唯一性,因?yàn)槲覀冋谟昧銇頊y試計(jì)數(shù)。你真正想要的只是問我的值是否是壞數(shù)字。你寫的和我們說的一模一樣:如果我在badNumbers:
這是仍然是一個\$O(n)\$操作,但是會更快。正如在另一個答案中提到的,將壞數(shù)字轉(zhuǎn)換為一個集合將加快運(yùn)算速度,使之成為一個\$O(1)\$運(yùn)算。但是讓我們研究另一個選項(xiàng)。
減少數(shù)據(jù) 您的示例badNumbers=[37,7,22,15,49,60],l=3和r=48顯示出更多的低效。壞數(shù)字包含超出的數(shù)字。一遍又一遍地看那些數(shù)字(例如壞數(shù)字。計(jì)數(shù)(i) ==0或i(在badNumbers中)是浪費(fèi)時間的。
我們可以過濾掉“壞”的壞數(shù)字,這些壞數(shù)字只會浪費(fèi)時間。
badNumbers=[number for number in badNumbers if llt;=r]
組織數(shù)據(jù) 您正在循環(huán)處理候選數(shù)字,然后進(jìn)行有效搜索,查看候選號碼是否在壞號碼列表中。如果對該列表進(jìn)行了排序,則只需維護(hù)一個指向下一個不匹配錯誤數(shù)字的索引,并在每次找到匹配項(xiàng)時遞增該索引。
將該索引與上一個索引相結(jié)合步驟:
badNumbers=排序(如果llt;=r,則x代表x)
Now在您的示例中,badNumbers將是[7,15,22,37]
Now,it=iter(badNumbers)會創(chuàng)建一個迭代器遍歷列表,按順序,bad_number=next(it)會從列表中提取下一個錯誤的數(shù)字,我們也擺脫了上面提到的討厭的索引。
但是我真的很想擺脫第一個循環(huán),所以讓我們采取不同的方法。
Gap Length and End Posts [7,15,22,37]
在這個數(shù)組中,我們可以立即看到前兩個壞數(shù)之間有15-7-1個好數(shù),下一對之間有22-15-1個好數(shù),最后一對之間有37-22-1個壞數(shù)。這幾乎是所有我們需要得到最長的運(yùn)行良好的數(shù)字!
缺少的是列表開頭和結(jié)尾處的正確數(shù)字。我們可以通過添加一些“end posts”來解決這個問題,額外的壞數(shù)字超出了好的范圍end點(diǎn)數(shù):
baddumbers=[l-1]+排序(如果llt;=r,則x代表x)+[r+1]
為l=3和r=48,這將創(chuàng)建badNumbers=[2,7,15,22,37,49]。
現(xiàn)在,每對數(shù)字都可以用來確定
PairWise 由于我們想要成對地獲取數(shù)字,因此可以參考Python itertools庫以獲得適當(dāng)?shù)暮瘮?shù)。它不是內(nèi)置的,但是成對的配方可以從more-itertools安裝。
將這些數(shù)字作為一對,計(jì)算一對壞值之間的好值數(shù)目,并記住最大值。為了提高效率,可以將內(nèi)部計(jì)算的負(fù)1延遲到最后,因?yàn)閈$\max{(x\u i-1)}==\max{(x\u i)}-1\$
從更多itertools導(dǎo)入pairwisedef goodSegment(bad\u numbers,l,r):bad\u numbers=[l-1]+sorted(如果llt;=r,則x代表bad\u numbers)+[r+1]gap\u length=(b-a代表a,b in pairwise(bad_numbers))return max(gap_length)-1badNumbers=[5,4,2,15]l=1r=10 result=goodSegment(badNumbers,l,r)print(result) 如果沒有更多的itertools可用,您可以使一些東西幾乎等價于
def pairwise(numbers):return zip(numbers[:-1],numbers[1:]) 它可能更快,雖然它會占用三倍的內(nèi)存。
它是\$O(n*m)\$,因?yàn)閴臄?shù)字。計(jì)數(shù)(i) ,n和m是壞數(shù)的長度和從左到右的范圍。如果你將壞數(shù)轉(zhuǎn)換成一個集合,并檢查我是否在集合中,你可以將這個值減少到\$O(n+m)\$。
你在函數(shù)中做了很多不必要的事情。您只需要當(dāng)前數(shù)量和您在一行中看到的最大數(shù)量的數(shù)字,這些數(shù)字不在壞數(shù)字中。您不需要使用任何list.
Btw,在一些地方,您可以通過使用elif而不是使用else和嵌套if/else塊來使當(dāng)前代碼更平坦。特別是如果i==r:和len(子范圍)==1:。這些可以更改為elif,然后底部的else塊可以不縮進(jìn)。- End
免責(zé)聲明:
本頁內(nèi)容僅代表作者本人意見,若因此產(chǎn)生任何糾紛由作者本人負(fù)責(zé),概與琴島網(wǎng)公司無關(guān)。本頁內(nèi)容僅供參考,請您根據(jù)自身實(shí)際情況謹(jǐn)慎操作。尤其涉及您或第三方利益等事項(xiàng),請咨詢專業(yè)人士處理。