算法進化歷程2燈泡開關

出場人物介紹

小美:小學4年級學生堪侯,參加了學校的編程興趣小組舷夺,已經了解了Python語言的基本語法,能夠看懂一些簡單的程序攻旦。她做事風風火火喻旷,對所有的事情都很好奇,喜歡打破砂鍋問到底牢屋,是一個叫人又愛又恨的小丫頭。

阿福:一個酷愛編程的8年級男生槽袄。大家都說他長得像國寶大熊貓烙无,動作緩慢,憨態(tài)可掬遍尺。他做事情確實夠慢的截酷,連說話也慢條斯理,可是他一點也不擔心乾戏,他常常說:“慢就是快迂苛,只要堅持下去,蝸牛也能爬上金字塔鼓择∪茫”

古老師:雖然年近不惑,但依然對生活充滿熱情呐能∧畎幔“愛生活愛運動”是他的人生信條,和孩子們一起編程是他最大的樂趣摆出。他神出鬼沒朗徊,總是在孩子們最需要幫助的時候出現(xiàn)。當然偎漫,你也不能動不動就找古老師爷恳,因為他很忙,非常非常忙象踊。所以温亲,遇到問題還是自己先思考吧。


算法進化歷程之燈泡開關

阿福:最近古老師讓我到力扣(leetcode)網去刷題通危,我遇到了一個很有趣的題目铸豁。

小美:是嗎?趕快拿出來瞧瞧菊碟。


題目1:

燈泡開關节芥。

n個燈排成一排,依次編號為1-n,開始時都是關著的⊥纺鳎現(xiàn)進行如下操作: 第 1 輪蚣驼,所有電燈的按鈕按動一次;第2 輪相艇,所有編號為2的倍數(shù)的電燈按鈕按動一次颖杏;第3輪,所有編號為3的倍數(shù)的電燈的按鈕按動一次坛芽;……第n 輪留储,所有編號為n的倍數(shù)的電燈的按鈕按動一次。最后請統(tǒng)計?n?輪后有多少只電燈是亮的咙轩。

函數(shù)功能:統(tǒng)計?n?輪后有多少只電燈是亮的获讳。

函數(shù)名:bulbSwitch(n:int)-> int

參數(shù)表:n-- 燈的數(shù)量。

返回值:?n?輪后亮著的燈的數(shù)量活喊。

示例1:n=3丐膝,則返回1。

解釋:初始時钾菊,燈泡狀態(tài) [關閉, 關閉, 關閉]帅矗;第一輪后, 燈泡狀態(tài) [開啟, 開啟, 開啟];

第二輪后煞烫,燈泡狀態(tài) [開啟, 關閉, 開啟]浑此;第三輪后, 燈泡狀態(tài) [開啟, 關閉, 關閉]。

故第3輪后红竭,只有編號為1的燈泡是亮的尤勋。

示例2:n=10,則返回3茵宪。

解釋:第10輪后最冰,編號為1,4,9的燈泡是亮的。


小美:我感覺這道題不難啊稀火,用模擬算法就能解決暖哨。我們可以分別用0和1表示燈泡的暗亮狀態(tài),然后模擬整個開關燈過程凰狞,最后統(tǒng)計值為1的元素個數(shù)篇裁。


代碼1:

def bulbSwitch(n: int) -> int:

??? a = [0] * (n + 1) #初始時所有燈泡均關閉

??? for i in range(1, n + 1):

??????? for j in range(i, n + 1, i): #只處理i的倍數(shù)

??????????? a[j] = 1 - a[j] #實現(xiàn)0和1的相互轉換

??? return sum(a)#對列表a求和,即統(tǒng)計值為1的元素個數(shù)

阿福:這個思路簡單直接赡若。我一開始也是這樣想的达布,可是提交代碼以后,系統(tǒng)判定超時逾冬。

小美:超時黍聂?那說明我們的算法效率太低了躺苦。可是我已經盡可能對代碼進行優(yōu)化了啊产还。

阿福:沒錯匹厘,如果使用模擬算法的話,你的代碼已經寫得很好了脐区∮希可是模擬算法本身就不是高效的算法。這道題目要用到一些數(shù)學知識牛隅。

小美:數(shù)學知識炕柔?

阿福:沒錯,就是數(shù)學知識倔叼。請你仔細觀察一下汗唱,n輪操作下來,編號為i的開關切換的次數(shù)與i有什么關系丈攒?例如當n=10時,編號為6的開關總共切換了幾次授霸?分別是在第幾輪被切換過巡验?

小美:當n=10時,編號為6的開關在第1輪碘耳、第2輪显设、第3輪和第6輪被切換過,總共切換了4次辛辨。

?阿福:編號為9的開關呢捕捂?

小美:當n=10時,編號為9的開關在第1輪斗搞、第3輪和第9輪被切換過指攒,總共切換了3次。

阿福:看出規(guī)律來了嗎僻焚?

小美:規(guī)律允悦?哦,我看出來了虑啤。編號為i的開關切換的次數(shù)恰好為i的因數(shù)個數(shù)隙弛。

阿福:沒錯,正是這樣狞山!我們可以根據(jù)編號i的因數(shù)個數(shù)來判斷燈的暗亮狀態(tài)全闷,若i的因數(shù)個數(shù)為奇數(shù),則最后該燈亮萍启。

小美:道理是沒錯总珠,但怎么判斷i的因數(shù)個數(shù)是奇數(shù)還是偶數(shù)呢?

阿福:你再觀察一下6和9的因數(shù)分布情況。

小美:我發(fā)現(xiàn)了姚淆,因數(shù)都是對稱分布的孕蝉。例如,6=1*6=2*3腌逢,9=1*9=3*3降淮。i的因數(shù)以平方根為軸對稱分布,成對出現(xiàn)搏讶。如果i是完全平方數(shù)佳鳖,它的因數(shù)有奇數(shù)個(因為平方根只能和自己配對),否則就是偶數(shù)個媒惕。

?阿福:沒錯系吩,n輪操作下來,只有編號為完全平方數(shù)的燈泡亮妒蔚,我們就只需統(tǒng)計有多少個完全平方數(shù)就行了穿挨。代碼如下:


代碼2:

def bulbSwitch2(n: int) -> int:

??? s = 0

??? for i in range(1, n + 1):

??????? sqr = int(i ** 0.5)

??????? if i == sqr * sqr: #統(tǒng)計完全平方數(shù)的個數(shù)

??????????? s += 1

??? return s

小美:阿福真棒!

阿福:唉肴盏,當時我也覺得自己挺棒的科盛。可代碼提交以后菜皂,系統(tǒng)仍判定超時贞绵。

小美:這都不行啊恍飘?難道還有什么更高效的方法嗎榨崩?會不會是因為開根號的操作太耗時了?

阿福:我也猜測是這個原因章母∧钢耄可不開根號還能怎么辦呢?

古老師:阿福胳施,你采用的是枚舉算法溯祸,那你還記得枚舉算法要考慮的因素是哪幾個嗎?

小美:這個我知道舞肆!枚舉算法要考慮的因素有枚舉變量焦辅,枚舉范圍和枚舉條件。

古老師:不錯椿胯,那在這個題目中筷登,它們分別是什么呢?

阿福:枚舉變量是i哩盲,枚舉范圍是[1, n]前方,枚舉條件是判斷i是否為完全平方數(shù)狈醉,通過計算i的平方根sqr來判斷枚舉條件是否成立。

古老師:是啊惠险,這個算法中最耗時的地方就是計算sqr的值苗傅。那你們有沒有想過逆向思維,枚舉sqr班巩,利用sqr來求i呢渣慕?

小美:逆向思維?枚舉sqr抱慌?哦逊桦,我想到了!可以從1開始遞增sqr的值抑进,判斷sqr *

sqr是否小于等于 n强经,最后sqr的值就是完全平方數(shù)的個數(shù)。

阿福:不對寺渗, sqr的值減一才是正解匿情,因為最后一個sqr已經不滿足條件了。

小美:沒錯信殊,是要減一码秉。還是阿福考慮周到鸡号。


代碼3:

def bulbSwitch3(n:int) -> int:

??? sqr = 1

?? ?while sqr * sqr <= n:

??????? sqr += 1

??? return sqr - 1 #最后一個sqr已經不滿足條件了

阿福:哇,通過了须鼎!還戰(zhàn)勝了62.72%的用戶呢鲸伴。

古老師:不錯不錯!看來你對完全平方數(shù)已經有一定的了解了晋控。

小美:一定的了解汞窗?難道我們研究的還不夠透徹嗎?

古老師:應該說研究得比較透徹了赡译。但請你再仔細觀察一下仲吏,[1, n]范圍內的完全平方數(shù)個數(shù)與n到底有什么關系呢?

小美:這還有關系蝌焚?

阿福:我把n和[1, n]范圍內的完全平方數(shù)個數(shù)s組成一個元組(n, s)裹唆,列舉了[1, 20]范圍內的(n, s)值如下,(1, 1),(2, 1),(3, 1),(4, 2),(5, 2),(6, 2),(7, 2),(8, 2),(9, 3),(10, 3),(11, 3),(12, 3),(13, 3),(14, 3),(15,3),(16, 4),(17, 4),(18, 4),(19, 4),(20, 4)只洒。小美许帐,你發(fā)現(xiàn)有什么規(guī)律沒有?

小美:規(guī)律毕谴?我看到了成畦,只有當n等于完全平方數(shù)的時候距芬,s的值才會增加。

阿福:沒錯循帐!而且s的值恰好等于n的平方根框仔。

小美:那就好辦了!代碼簡單得很拄养!


代碼4:

def bulbSwitch4(n:int) -> int:

return int(n ** 0.5) #[1, n]范圍內的完全平方數(shù)個數(shù)恰好為其平方根

古老師:果然是高手啊离斩,觀察力一流!看你們這么厲害衷旅,我就再給你們出一道題目吧捐腿。題目不難,就是把上一題稍微改動一下柿顶。


題目2:

哪些電燈是亮的茄袖。

n個燈排成一排,依次編號為1-n嘁锯,開始時都是關著的∠芟椋現(xiàn)進行如下操作: 第 1 輪,所有電燈的按鈕按動一次家乘;第2 輪蝗羊,所有編號為2的倍數(shù)的電燈按鈕按動一次;第3輪仁锯,所有編號為3的倍數(shù)的電燈的按鈕按動一次耀找;……第n 輪,所有編號為n的倍數(shù)的電燈的按鈕按動一次业崖。最后請輸出?n?輪后有哪些電燈是亮的野芒。

函數(shù)功能:輸出?n?輪后有哪些電燈是亮的。

函數(shù)名:bulbSwitch(n:int)-> list

參數(shù)表:n-- 燈的數(shù)量双炕。

返回值:一個存儲了所有亮燈編號的列表狞悲。

示例1:n=10,則返回[1, 4, 9]妇斤。

示例2:n=30拿穴,則返回[1, 4, 9, 16, 25]奋献。


小美:好像沒什么區(qū)別嘛历恐。

阿福:區(qū)別還是有的角寸,需要輸出具體哪些電燈是亮的。這樣一來就不能直接套用數(shù)學公式了顷编。

古老師:雖然不能直接套用數(shù)學公式戚炫,但是前面總結的數(shù)學規(guī)律還是有用的。也別想得太復雜媳纬,其實只要把前面的代碼1双肤、2施掏、3修改一下就行了。好了茅糜,我只能說這么多了七芭,剩下的自己去琢磨吧。拜拜咯蔑赘。




彩蛋:

小美:只要把代碼1狸驳、2、3修改一下就行了缩赛?

阿福:沒錯耙箍,前面我們做的是統(tǒng)計工作,現(xiàn)在只要把每個亮燈的編號都存儲起來就行了酥馍。這樣吧辩昆,你修改代碼1,我來修改代碼2和代碼3旨袒。

小美:好的汁针,沒問題。


代碼4:

分別用0和1表示燈泡的暗亮狀態(tài)砚尽,然后模擬整個開關燈過程施无,最后輸出值為1的元素

def bulbSwitch4(n:int) -> list:

??? a = [0] * (n + 1) #初始時所有燈泡均關閉

??? for i in range(1, n + 1):

??????? for j in range(i, n + 1, i):

??????????? a[j] = 1 - a[j]

return [i for i in range(n + 1) if a[i] == 1]

代碼5:

編號為完全平方數(shù)的燈泡亮,枚舉i必孤,計算sqr

def bulbSwitch5(n:int) -> list:

??? res = []

??? for i in range(1, n + 1):

??????? sqr = int(i ** 0.5)

??????? if i == sqr * sqr:

??????????? res.append(i)

return res

代碼6:

編號為完全平方數(shù)的燈泡亮猾骡,枚舉sqr,存儲sqr*sqr

def bulbSwitch6(n:int) -> list:

??? res = []

??? sqr = 1

??? while sqr * sqr <= n:

??????? res.append(sqr * sqr)

??????? sqr += 1

??? return res

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末敷搪,一起剝皮案震驚了整個濱河市卓练,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌购啄,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘱么,死亡現(xiàn)場離奇詭異狮含,居然都是意外死亡,警方通過查閱死者的電腦和手機曼振,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門几迄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人冰评,你說我怎么就攤上這事映胁。” “怎么了甲雅?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵解孙,是天一觀的道長坑填。 經常有香客問我,道長弛姜,這世上最難降的妖魔是什么脐瑰? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮廷臼,結果婚禮上苍在,老公的妹妹穿的比我還像新娘。我一直安慰自己荠商,他們只是感情好寂恬,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著莱没,像睡著了一般初肉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上郊愧,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天朴译,我揣著相機與錄音,去河邊找鬼属铁。 笑死眠寿,一個胖子當著我的面吹牛,可吹牛的內容都是我干的焦蘑。 我是一名探鬼主播盯拱,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼例嘱!你這毒婦竟也來了狡逢?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤拼卵,失蹤者是張志新(化名)和其女友劉穎奢浑,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腋腮,經...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡雀彼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了即寡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徊哑。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖聪富,靈堂內的尸體忽然破棺而出莺丑,到底是詐尸還是另有隱情,我是刑警寧澤墩蔓,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布梢莽,位于F島的核電站萧豆,受9級特大地震影響,放射性物質發(fā)生泄漏蟹漓。R本人自食惡果不足惜炕横,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望葡粒。 院中可真熱鬧份殿,春花似錦、人聲如沸嗽交。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夫壁。三九已至拾枣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盒让,已是汗流浹背梅肤。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留邑茄,地道東北人姨蝴。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像肺缕,于是被迫代替她去往敵國和親左医。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內容

  • 在C語言中,五種基本數(shù)據(jù)類型存儲空間長度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 3,339評論 0 2
  • 計算機二級C語言上機題庫(南開版) 1.m個人的成績存放在score數(shù)組中同木,請編寫函數(shù)fun,它的功能是:將低于平...
    MrSunbeam閱讀 6,336評論 1 42
  • 總結一下常見的排序算法浮梢。 排序分內排序和外排序。內排序:指在排序期間數(shù)據(jù)對象全部存放在內存的排序彤路。外排序:指在排序...
    jiangliang閱讀 1,336評論 0 1
  • 列表的紛爭之二進制編碼 小美:最近數(shù)學老師給我們玩了有趣的猜年齡游戲秕硝,他顯示了6張表格,你只要觀察這6張表格洲尊,然后...
    巧若拙閱讀 1,115評論 0 1
  • 阿福:小美缝裤,聽說你學過海龜繪圖,能幫我用turtle來畫一張棋譜嗎颊郎? 小美:什么棋譜? 阿福:就是一張9路圍棋盤的...
    巧若拙閱讀 839評論 0 1