【原創(chuàng)連載】算法素顏(第2篇):掃雷還可以這樣玩

創(chuàng)作時(shí)間:2019-03-18

作者:周林

版權(quán)所有矛双,轉(zhuǎn)載請(qǐng)聯(lián)系作者獲取授權(quán)牛哺、并注明作者與出處

周林的簡(jiǎn)書主頁(yè)

周林的CSDN博客主頁(yè)

周林的知乎主頁(yè)




?????? 上篇文章介紹了算法的本質(zhì)和基本概念达传,這次我們用實(shí)際的問題來做算法實(shí)戰(zhàn)篙耗。

?????? 假設(shè)如下場(chǎng)景: 公司新年晚會(huì)進(jìn)行奪寶游戲,獎(jiǎng)品是最新款的智能手機(jī)宪赶、VR游戲機(jī)宗弯、便攜電腦三件套。游戲規(guī)則如下: 當(dāng)主持人宣布游戲開始的時(shí)候搂妻,每位員工的手機(jī)上會(huì)同時(shí)收到兩組數(shù)字(數(shù)組中的每個(gè)數(shù)字都是正整數(shù)且兩兩不等)和一個(gè)目標(biāo)正整數(shù)蒙保。員工需要在兩組數(shù)字中分別取兩個(gè)數(shù)字相加,使得相加的結(jié)果與目標(biāo)正整數(shù)最接近欲主。哪位員工先做出結(jié)果,那么獎(jiǎng)品就歸誰(shuí)扁瓢。為了使贏率最高详恼,請(qǐng)問應(yīng)該采用什么樣的策略或者方法引几?

?????? 顯然敞掘,這是在對(duì)一個(gè)特定問題找方法玖雁。那么根據(jù)上篇文章所講到的茄菊,這就是在求算法疯潭。 那么如何算法求解呢?答案就在上篇文章提到的“樸素而廣泛的方法論”中面殖。這個(gè)方法論其實(shí)就是算法求解的套路竖哩。

套路第一步:重新定義問題,結(jié)構(gòu)化描述

?????? 原問題是生活場(chǎng)景脊僚,要轉(zhuǎn)換成結(jié)構(gòu)化問題描述相叁。結(jié)構(gòu)化描述分為如下兩步:數(shù)據(jù)與規(guī)則抽取、數(shù)據(jù)結(jié)構(gòu)選擇與轉(zhuǎn)化辽幌。


數(shù)據(jù)與規(guī)則抽取

?????? 數(shù)據(jù)的來源:數(shù)據(jù)一般在原問題描述中以名詞增淹、量詞形式出現(xiàn)

?????? 數(shù)據(jù)的摘取:并不是所有的名詞和量詞都是有效數(shù)據(jù)乌企。

?????? 很明顯虑润,只有和問題求解相關(guān)的名詞和量詞才有意義〖咏停“問題求解”是動(dòng)作拳喻,與動(dòng)詞相關(guān)。 那么是不是所有的動(dòng)詞都有效呢猪腕?也不是冗澈。只有和規(guī)則相關(guān)的動(dòng)詞才是有效的。

???????規(guī)則的發(fā)掘:規(guī)則就是抵達(dá)結(jié)果的條件陋葡。

?????? 根據(jù)上面的定義亚亲, 不難看出:

?????? 數(shù)據(jù)是:兩組數(shù)字(數(shù)組中的每個(gè)數(shù)字都是正整數(shù)且兩兩不等)、一個(gè)目標(biāo)整數(shù)

???? ?規(guī)則是:從兩組數(shù)字中分別取兩個(gè)數(shù)字相加腐缤,相加的結(jié)果必須與目標(biāo)正整數(shù)最接近

數(shù)據(jù)結(jié)構(gòu)選擇與轉(zhuǎn)化

?????? 上篇文章已經(jīng)講到了:算法的依托是數(shù)據(jù)結(jié)構(gòu)捌归。如果把算法看做設(shè)計(jì)域的話,那么數(shù)據(jù)結(jié)構(gòu)就是連接問題域到設(shè)計(jì)域的橋梁岭粤。那么如何選取合適的數(shù)據(jù)結(jié)構(gòu)呢陨溅?答案是:對(duì)上一步摘取的數(shù)據(jù)進(jìn)行類型聯(lián)想、關(guān)聯(lián)绍在。


?????? 上一步中门扇,我們已經(jīng)摘取了數(shù)據(jù)——兩組數(shù)和一個(gè)正整數(shù)。很明顯偿渡,這里涉及到兩個(gè)類型:數(shù)組和整數(shù)臼寄。而這兩個(gè)屬于基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)類型,至此數(shù)據(jù)結(jié)構(gòu)選擇問題解決了溜宽。接下來就是要對(duì)摘取的數(shù)據(jù)吉拳,基于選擇的數(shù)據(jù)結(jié)構(gòu)進(jìn)行轉(zhuǎn)化——“重整化”:

?????? ?兩組數(shù)字(數(shù)組中的每個(gè)數(shù)字都是正整數(shù)且兩兩不等)=> int A[]; int B[];

?????? ?目標(biāo)正整數(shù) => int c;

??????? 聰明的你,一定會(huì)問一個(gè)問題:數(shù)據(jù)結(jié)構(gòu)的選擇僅僅就在這一步?jīng)Q定嗎适揉? 答案是否定的留攒。數(shù)據(jù)結(jié)構(gòu)的選擇會(huì)貫穿整個(gè)算法設(shè)計(jì)煤惩,是一個(gè)不斷迭代的過程。后面部分會(huì)詳細(xì)闡述炼邀。

套路第二步:?jiǎn)栴}歸類

?????? 算法問題的基本類型:搜索魄揉、排序、規(guī)劃拭宁、計(jì)算洛退。

????? ?回到當(dāng)前問題,根據(jù)問題描述杰标,顯然屬于搜索類型兵怯。

套路第三步:經(jīng)驗(yàn)匹配

?????? 現(xiàn)在我們來翻看已有的搜索算法,看看有沒有能與當(dāng)前問題匹配的腔剂。

?????? 理論上有3種情況:

?????? 第1種情況媒区,100%匹配,此時(shí)直接“拿來主義”掸犬;

???????第2種情況袜漩,部分匹配,此時(shí)可在已有算法基礎(chǔ)上進(jìn)行調(diào)整登渣、組合或者改良噪服;

?????? 第3種情況毡泻,完全不匹配胜茧,此時(shí)需要我們根據(jù)已有知識(shí)(甚至是跨學(xué)科知識(shí),比方說數(shù)學(xué)仇味、生物等)呻顽,創(chuàng)新性地開發(fā)新算法。

?????? 針對(duì)搜索問題丹墨,我們有一個(gè)萬(wàn)能算法——“暴力搜索”廊遍,即遍歷每一種可能性,直到找到答案贩挣。但是這個(gè)算法要窮盡所有可能性喉前,所以帶來的時(shí)間和空間開銷通常都是巨大的,用上篇文章的術(shù)語(yǔ)來講王财,就是計(jì)算復(fù)雜度賊高卵迂。 為了給大家一個(gè)量化感覺,先用“暴力搜索”算法來解答這個(gè)題:

暴力搜索算法

?????? 對(duì)于數(shù)組A中的每一個(gè)元素進(jìn)行遍歷:

????????????? 設(shè)當(dāng)前元素為A[i]绒净,則:

????????????? 遍歷數(shù)組b中的每一個(gè)元素B[j]:

??????????? (i)計(jì)算A[i]+B[j]的值见咒,將所求的值記為t;

??????????????(ii) 計(jì)算t-c的絕對(duì)值|t-c|,記為k;

????????????? (iii) 如果當(dāng)前的k比歷史的k泄医(k的初值可以設(shè)成一個(gè)極大值)改览,那么:

????????????????????????? 將 {A[i], B[j]}取代之前的候選結(jié)果下翎,作為新的候選結(jié)果

??????? 待所有的遍歷結(jié)束,最終的候選結(jié)果就是所要求的解宝当。

???????上面的算法有兩重循環(huán)视事,所以暴力搜索時(shí)間復(fù)雜度為O(La x Lb)。 其中La表示數(shù)組a中元素的個(gè)數(shù)今妄,Lb表示數(shù)組b中元素的個(gè)數(shù)郑口。 隨著La和Lb的增大,復(fù)雜度以兩者乘積速度上升盾鳞。

???????那么如何對(duì)暴力算法進(jìn)行優(yōu)化呢犬性?

?????? 關(guān)于復(fù)雜度的計(jì)算,我會(huì)在下篇文章中詳細(xì)介紹腾仅。

套路第四步:算法優(yōu)化三步走

步驟1:找到算法性能瓶頸源頭

???????????? 稍微分析一下乒裆,就明白:上述暴力搜索算法的開銷在于窮盡了所有元素。

步驟2:對(duì)源頭進(jìn)行改造

???????????? 那么是否可以避免窮盡所有元素而得到結(jié)果呢推励?

???????????? 換言之鹤耍,是否可以只比較部分元素、其他元素就自然被排除了呢验辞?

???????????? 要得到這樣的效果稿黄,顯然我們需要一種性質(zhì)——這種性質(zhì)必須是容易獲得的:

??????????? ?要么可以直接從當(dāng)前數(shù)據(jù)中獲取,要么可以通過已有方法(算法)獲取跌造。

??????????? 最容易想到的就是有序性杆怕,這種性質(zhì)可以通過排序算法獲取。

?????????? ?我們可以用快速排序算法對(duì)A數(shù)組和B組數(shù)進(jìn)行排序壳贪,將排序后的元素按照下圖放置: (為了方便表示陵珍,我們假設(shè)A數(shù)組是10個(gè)元素,B數(shù)組是11個(gè)元素)


?????????? 上圖中的每個(gè)方格就是用來存放相加結(jié)果的违施。很顯然互纯,暴力搜索就是對(duì)上圖中的每個(gè)方格都做了計(jì)算。

?????????? 現(xiàn)在我們要做的磕蒲,就是利用有序性留潦,避開盡可能多的方格。

?????????? 我們從右上角方格[A10, B1]開始遍歷:

?????????? 記s[A10, B1] = A10 + B1辣往,則:

??????????? (i) 如果s[A10, B1] == 目標(biāo)正整數(shù)c兔院,那么元素對(duì){A10, B1}即為所求解

??????????? (ii) 如果s[A10, B1] < 目標(biāo)正整數(shù)c排吴, 那么所有與[A10秆乳,B1]在同一排的方格都不用計(jì)算了

?????????????????原因如下:因?yàn)锳1<=A2<=...<=A9<=A10,所以s[A1, B1] <= s[A2, B1] <= ... <= s[A10, B1],

?????????????????從而這些s距離c都比s[10, B1]遠(yuǎn)屹堰,都不是所求解肛冶。

????????????(iii) 類似地,如果s[A10, B1] > 目標(biāo)正整數(shù)c扯键,那么所有與A[10, B1]在同一列的方格都不用計(jì)算了

?????????? 顯然睦袖,按照對(duì)角線方向來遍歷,每遍歷一個(gè)方格荣刑,就可以避開一排或者一列的方格馅笙,感覺就像在玩掃雷游戲:)







步驟3:驗(yàn)證

??????? 現(xiàn)在我們來驗(yàn)證一下優(yōu)化后的算法的復(fù)雜度:

??????? 整個(gè)算法分成兩部分:

??????? 第1部分是快速排序±骺鳎快速排序算法的時(shí)間復(fù)雜度是O(nlogn)董习,所以這部分的時(shí)間復(fù)雜度是O(MAX(LalogLa, LblogLb))

???????? 第2部分是掃雷遍歷。這部分最壞的情況就是走完整個(gè)對(duì)角線爱只。此時(shí)共遍歷La+Lb-1個(gè)方格皿淋,時(shí)間復(fù)雜度是O(La+Lb)

???????? 兩者相加得到最壞情況下的整體時(shí)間復(fù)雜度為:O(MAX(LalogLa, LblogLb)+La+Lb)


本原創(chuàng)系列同步在以下自媒體上更新,敬請(qǐng)關(guān)注:

CSDN:https://blog.csdn.net/jintianyishiyeai/

知乎:https://www.zhihu.com/people/cubiezhou2017

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恬试,一起剝皮案震驚了整個(gè)濱河市窝趣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌训柴,老刑警劉巖哑舒,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異幻馁,居然都是意外死亡洗鸵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門宣赔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來预麸,“玉大人瞪浸,你說我怎么就攤上這事儒将。” “怎么了对蒲?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵钩蚊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蹈矮,道長(zhǎng)砰逻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任泛鸟,我火速辦了婚禮蝠咆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己刚操,他們只是感情好闸翅,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著菊霜,像睡著了一般坚冀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鉴逞,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天记某,我揣著相機(jī)與錄音,去河邊找鬼构捡。 笑死液南,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的勾徽。 我是一名探鬼主播贺拣,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼捂蕴!你這毒婦竟也來了譬涡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤啥辨,失蹤者是張志新(化名)和其女友劉穎涡匀,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溉知,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡陨瘩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了级乍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舌劳。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖玫荣,靈堂內(nèi)的尸體忽然破棺而出甚淡,到底是詐尸還是另有隱情,我是刑警寧澤捅厂,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布贯卦,位于F島的核電站,受9級(jí)特大地震影響焙贷,放射性物質(zhì)發(fā)生泄漏撵割。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一辙芍、第九天 我趴在偏房一處隱蔽的房頂上張望啡彬。 院中可真熱鬧羹与,春花似錦、人聲如沸庶灿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)跳仿。三九已至诡渴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間菲语,已是汗流浹背妄辩。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留山上,地道東北人眼耀。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像佩憾,于是被迫代替她去往敵國(guó)和親哮伟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359