文章摘抄至《算法之美》,附帶了Python模擬。
不久前,我去觀看草地網(wǎng)球錦標(biāo)賽,一位十分沮喪的運(yùn)動(dòng)員引起了我對(duì)球賽目前采用的名次確定方法的注意。這位運(yùn)動(dòng)員在比賽中早早落敗,因此徹底失去了獲得獎(jiǎng)牌的機(jī)會(huì)。令他感到屈辱的是,獲得第二名的是他知道的一名遠(yuǎn)不如自己的運(yùn)動(dòng)員。
普通觀眾可能會(huì)把這種“哀嘆”歸咎于失敗的痛苦,但道奇森并不是一個(gè)同情心泛濫的人,他是牛津大學(xué)數(shù)學(xué)系講師,因此,在聽(tīng)到運(yùn)動(dòng)員的抱怨之后,他決定對(duì)體育賽事展開(kāi)深入調(diào)查。道奇森不僅僅是一個(gè)數(shù)學(xué)家(其實(shí)他幾乎不記得自己是從事數(shù)學(xué)研究的)?,F(xiàn)在,反而是他的筆名——?jiǎng)⒁姿埂た_爾更加廣為人知。他以這個(gè)筆名寫(xiě)出了《愛(ài)麗絲漫游奇境記》以及大量其他深受歡迎的文學(xué)作品。他還將他的數(shù)學(xué)知識(shí)與文學(xué)天賦相結(jié)合,完成了一篇知名度略低的文章——《草地網(wǎng)球錦標(biāo)賽:正確的名次確定方法以及現(xiàn)行方法辨誤》。
道奇森針對(duì)的是單一淘汰賽。在這種賽制下,運(yùn)動(dòng)員兩兩對(duì)決,只要輸?shù)粢粓?chǎng)比賽,就會(huì)被淘汰出局。道奇森的理由非常有說(shuō)服力,他認(rèn)為,貨真價(jià)實(shí)的第二名有可能是被第一名淘汰的任何人,而不一定是最后才被淘汰的那名運(yùn)動(dòng)員。
直白地說(shuō),銀牌是一種假象?!白鳛橐粋€(gè)數(shù)學(xué)事實(shí),”他繼續(xù)寫(xiě)道,“實(shí)力排第二位的運(yùn)動(dòng)員獲得應(yīng)得名次的機(jī)會(huì)只有16/31。而最優(yōu)秀的4名運(yùn)動(dòng)員獲得與實(shí)力相稱名次的機(jī)會(huì)非常小,發(fā)生的概率為1/12!”
import copyimport randomclass Participants(): def __init__(self,*_participants): self.name = _participants[0] # 1號(hào)球員 self.performance =_participants[1] # 自身成績(jī) self.racePlaces = _participants[2] # 比賽名次# 實(shí)例100個(gè)選手,并且假設(shè)從5號(hào)以后的選手,實(shí)例都不如前4個(gè)arrPart=[]arrPart.append(Participants("No.1",100,0,0))arrPart.append(Participants("No.2",99,0,0))arrPart.append(Participants("No.3",98,0,0))arrPart.append(Participants("No.4",97,0,0))for i in range(5,101): arrPart.append(Participants(f"No.{i}", random.randint(0,96), 0, 0))# 單場(chǎng)比賽(傳入2個(gè)人員,和名次)返回,勝利者、失敗者def race(one,two,topNum): unitRace=[] if(one.performance > two.performance): print(f"{one.name}和{two.name}比賽,{one.name}勝利") one.racePlaces=topNum two.racePlaces=topNum-1 unitRace.append(one) unitRace.append(two) return one,two else: print(f"{one.name}和{two.name}比賽,{two.name}勝利") two.racePlaces=topNum-1 unitRace.append(two) one.racePlaces=topNum unitRace.append(one) return two,one# 排位開(kāi)始def knockout(all): arrVictory=[] #保存勝利者 # 選出前4名后結(jié)束 if(len(all)<=3): print("++++++++++++++++++=================") print(all[1].name) return all # 依次進(jìn)行兩兩比賽,同批次淘汰賽只參加一次 while( len(all) > 1 ): topNum=len(all) r=random.randint(0,len(all)-1) one=all[r] # 參賽后,從當(dāng)前候選名單刪除 all.remove(one) r=random.randint(0,len(all)-1) two=all[r] all.remove(two) victory,fail=race(one,two,topNum) print(victory.name) arrVictory.append(victory) # 添加勝利者 # 沒(méi)有進(jìn)行匹配的直接晉級(jí) if( len(all) == 1): arrVictory.append(all[0]) print("***********************--------------------------") # 下一輪淘汰賽 return knockout(arrVictory)# 統(tǒng)計(jì)1000次模擬種有幾次實(shí)力3號(hào)選手能進(jìn)前三isNO2count=0for i in range(1000): arrPart1=copy.copy(arrPart) victorys=knockout(arrPart1) for v in victorys: if v.name=="No.3": print("名次:%d"%(v.racePlaces)) isNO2count += 1 breakprint(isNO2count)
== 看輸出結(jié)果,我們很容易發(fā)現(xiàn),結(jié)果在22-28%之間徘徊。 ==
而只有把if v.name==‘No.3’:的No.3改成No.1才會(huì)是100%。
盡管道奇森的文章犀利有力,卻沒(méi)有對(duì)草地網(wǎng)球產(chǎn)生任何影響。他提出應(yīng)該采取三敗淘汰制(根據(jù)這種賽制,擊敗過(guò)你的運(yùn)動(dòng)員如果落敗,也有可能導(dǎo)致你隨之出局),但是這個(gè)提議根本沒(méi)有人理會(huì)。不過(guò),雖然道奇森的解決方案實(shí)施起來(lái)有很大的難度,但是他在這個(gè)問(wèn)題上的看法仍然是有道理的。(可惜的是,至今為止,在單淘汰賽中,仍然會(huì)頒發(fā)銀牌。)不過(guò),道奇森的邏輯還給我們帶來(lái)了一個(gè)更加深刻的認(rèn)識(shí)。我們?nèi)祟惒粌H會(huì)對(duì)數(shù)據(jù)、財(cái)產(chǎn)進(jìn)行排序,還會(huì)把我們自己變成排序?qū)ο蟆?br />
世界杯、奧運(yùn)會(huì)、美國(guó)全國(guó)大學(xué)體育協(xié)會(huì)(NCAA)、美國(guó)全國(guó)橄欖球聯(lián)盟(NFL)、美國(guó)全國(guó)曲棍球聯(lián)合會(huì)(NHL)、美國(guó)職業(yè)籃球聯(lián)賽(NBA)和美國(guó)職業(yè)棒球大聯(lián)盟(MLB),所有這些賽事都毫無(wú)疑問(wèn)地使用了排序程序,利用賽季、排位賽和季后賽等算法排出先后關(guān)系。體育運(yùn)動(dòng)中的循環(huán)賽制就利用了算法。如果一共有n支運(yùn)動(dòng)隊(duì),那么每支運(yùn)動(dòng)隊(duì)最終都要和其余n-1支隊(duì)伍比賽。這種賽制雖然可以說(shuō)是最全面的,但也最費(fèi)時(shí)費(fèi)力。
讓每一支運(yùn)動(dòng)隊(duì)都與其他所有隊(duì)伍比賽,就像在晚宴上讓客人兩兩擁抱一樣,最終會(huì)需要可怕的O(n2)次角逐。排位賽(在羽毛球、英式壁球和美式壁球等體育項(xiàng)目中比較常見(jiàn))對(duì)運(yùn)動(dòng)員進(jìn)行線性排序,每個(gè)球員都可以直接向排在前面一位的球員發(fā)起挑戰(zhàn),如果獲勝,則交換排位。排位賽就相當(dāng)于運(yùn)動(dòng)場(chǎng)上的冒泡排序,因此也是平方排序,需要O(n2)場(chǎng)比賽才能得到穩(wěn)定的排名。
「 大O符號(hào)表示法 」,即 T(n) = O(f(n))
在 大O符號(hào)表示法中,時(shí)間復(fù)雜度的公式是: T(n) = O( f(n) ),其中f(n) 表示每行代碼執(zhí)行次數(shù)之和,而 O 表示正比例關(guān)系,這個(gè)公式的全稱是:算法的漸進(jìn)時(shí)間復(fù)雜度。
** 在剛剛的演示代碼中,race函數(shù)的執(zhí)行次數(shù)就是一個(gè)時(shí)間復(fù)雜度的統(tǒng)計(jì),所以,該程序的時(shí)間復(fù)雜度為O(n log n) **
空間復(fù)雜度是對(duì)一個(gè)算法在運(yùn)行過(guò)程中臨時(shí)占用存儲(chǔ)空間大小的一個(gè)量度,同樣反映的是一個(gè)趨勢(shì),我們用 S(n) 來(lái)定義。
** 在剛剛的演示代碼中,一個(gè)人/同一時(shí)間,只有一個(gè)場(chǎng)地比賽,所以,它的空間復(fù)雜度為S(1) **
不過(guò),最流行的賽制可能還是分組淘汰——著名的“瘋狂三月”NCAA籃球賽就是其中一例?!隘偪袢隆卞\標(biāo)賽的賽程包含“64強(qiáng)賽”“32強(qiáng)賽”到“甜蜜16強(qiáng)”“8強(qiáng)賽”“最后4強(qiáng)”和總決賽。每一輪都會(huì)導(dǎo)致比賽人數(shù)減半。與我們熟悉的對(duì)數(shù)排序很像吧?這種賽制其實(shí)就是合并排序,先讓球隊(duì)無(wú)序配對(duì),然后進(jìn)行一輪又一輪的比較。
我們知道合并排序需要線性對(duì)數(shù)時(shí)間[即O(n log n)],因此,如果一共有64支隊(duì)伍,可以預(yù)計(jì)比賽只需要進(jìn)行6輪(一共192場(chǎng)),而采用排位賽或者循環(huán)賽,則需要多達(dá)63輪(2016場(chǎng))比賽。這是一個(gè)巨大的改進(jìn),說(shuō)明對(duì)數(shù)設(shè)計(jì)發(fā)揮了效用。
“瘋狂三月”有6輪比賽,似乎沒(méi)有問(wèn)題,但是怎么是192場(chǎng)比賽呢?
美國(guó)大學(xué)體育協(xié)會(huì)錦標(biāo)賽不是只有63場(chǎng)比賽嗎?
“瘋狂三月”其實(shí)不完全是一種合并排序法,因?yàn)樗](méi)有產(chǎn)生所有64支隊(duì)伍的完整排序。要對(duì)所有球隊(duì)進(jìn)行排名,我們需要增加一組比賽才能確定第二名,確定第三名時(shí)又需要增加一組比賽,以此類推,比賽的總場(chǎng)次就會(huì)是一個(gè)線性對(duì)數(shù)函數(shù)。但是“瘋狂三月”沒(méi)有采取這種賽制。相反,就像道奇森抱怨的草地網(wǎng)球錦標(biāo)賽一樣,它采用的是一種單一淘汰制,被淘汰的球隊(duì)是不排序的。這種賽制的優(yōu)勢(shì)在于它的線性時(shí)間。由于每場(chǎng)比賽正好淘汰一支隊(duì)伍,因此,要讓一支隊(duì)伍留到最后,一共需要n-1場(chǎng)比賽。這是一個(gè)線性數(shù)字。不足之處是,這種賽制只能決出第一名,無(wú)法給出名次表。
很多優(yōu)秀的算法,很容易在生活中找到案例,同時(shí)也可以把算法技巧用在生活和工作上。
書(shū)名為《算法之美–指導(dǎo)工作與生活的算法》
同時(shí)推薦一本《數(shù)據(jù)結(jié)構(gòu)與算法__Python語(yǔ)言描述_裘宗燕編著_北京:機(jī)械工業(yè)出版社》
我很少大范圍的推薦資料,知道什么是有用的,可以幫助自己少走很多彎路,需要的小伙伴,網(wǎng)盤(pán)自取:
鏈接: https://pan.baidu.com/s/1W8p4xXO7XaZiUxXgS9VjIQ 提取碼: qrej 復(fù)制這段內(nèi)容后打開(kāi)百度網(wǎng)盤(pán)手機(jī)App,操作更方便哦
最后,感謝大家三連關(guān)注,支持一波。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/121682.html
摘要:前言在開(kāi)發(fā)技術(shù)和應(yīng)用市場(chǎng)完全成熟的今天,有人希望深耕技術(shù)打造出自己的一片天地,也有人想廣泛學(xué)習(xí)在程序員市場(chǎng)中游刃有余。而這本書(shū)上千的引用論文,給我指明了一條系統(tǒng)學(xué)習(xí)理論的明路。 ...
必須要看的前言 本文風(fēng)格:以??簡(jiǎn)單易懂??的語(yǔ)言帶你徹底搞懂KNN,了解什么是有監(jiān)督學(xué)習(xí)算法。 認(rèn)真看完這篇文章,徹底了解KNN、了解監(jiān)督學(xué)習(xí)算法絕對(duì)是一樣很簡(jiǎn)單的事情。 注:本篇文章非常詳細(xì),同時(shí)我也附加了Python代碼,歡迎收藏后慢慢閱讀。 目錄 必須要看的前言監(jiān)督學(xué)習(xí)算法KNN/K近鄰算法1 算法原理1.1 實(shí)現(xiàn)過(guò)程1.2 距離的確定 2 算法的優(yōu)缺點(diǎn)3 算法的變種3.1 變...
??歡迎訂閱《從實(shí)戰(zhàn)學(xué)python》專欄,用python實(shí)現(xiàn)爬蟲(chóng)、辦公自動(dòng)化、數(shù)據(jù)可視化、人工智能等各個(gè)方向的實(shí)戰(zhàn)案例,有趣又有用!?? 更多精品專欄簡(jiǎn)介點(diǎn)這里 治愈生活的良方 就是保持對(duì)生活的熱愛(ài) 前言 哈嘍,大家好,我是一條。 每次和女朋友出去玩,拍照是必須的,天氣好還行,天氣要是不好,加上我這破手機(jī),那拍的簡(jiǎn)直慘不忍睹,自己都不過(guò)去。 但是沒(méi)什么能難倒程序員的,為了不挨罵,連夜寫(xiě)出去霧...
互聯(lián)網(wǎng)高速發(fā)展,隨著科技的進(jìn)步有一些崗位薪資出現(xiàn)了墊底的情況比如:生產(chǎn)制造、客服、行政等崗位。也有一些崗位薪資有了大幅度的增長(zhǎng):營(yíng)銷(xiāo)/運(yùn)營(yíng)、研發(fā)/開(kāi)發(fā),以及IT相關(guān)的崗位。 那么對(duì)于一個(gè)應(yīng)屆畢業(yè)生,并非計(jì)算機(jī)專業(yè)的該如何進(jìn)入IT這個(gè)領(lǐng)域呢? 推薦你來(lái)學(xué)習(xí)軟件測(cè)試,首先軟件測(cè)試只有20%的代碼,對(duì)文科生來(lái)說(shuō)是非常又好的。學(xué)習(xí)軟件測(cè)試的入行難度相對(duì)比開(kāi)發(fā)壓力小很多。就算是你想要選擇在二線城市就業(yè),不想...
閱讀 2275·2021-09-30 09:48
閱讀 3648·2021-09-24 10:27
閱讀 1805·2021-09-22 15:32
閱讀 2036·2021-08-09 13:44
閱讀 3585·2019-08-30 15:55
閱讀 1057·2019-08-29 17:12
閱讀 2019·2019-08-29 17:05
閱讀 2929·2019-08-29 13:43