計算機的世界每天都在發生著深刻的變化。新作業系統的發布、cpu效能的提公升、智慧型手機和平板電腦的流行、儲存介質的變化、雲的普及……這樣的變化數不勝數。
在這樣日新月異的時代中,「演算法」是不變的重要基石。要編寫高效率的程式,就需要優化演算法。無論開發工具如何進化,熟識並能靈活運用演算法仍然是對程式設計師的基本要求。
100%的程式設計師都想挑戰這四道有【等級區別】演算法趣題。
每個問題大致分為「問題」和「詳解」兩部分。
請各位先通讀問題描述,並動手編寫程式嘗試解題。在這個過程中,具體的實現方法是其次,更重要的是思考「通過哪些步驟來實現才能夠解決問題」。
每個問題都有思路講解和源**示例。請留意自己程式設計時在處理速度、可讀性等方面進行的優化,和本文的源**示例有什麼不同。如果事先看了思路講解和答案,就會失去解題的樂趣,所以這裡建議大家先程式設計解題,再看講解。
準備好了嗎?我們開始答題吧!
q1:入門
嘗試用程式設計解決問題
難度係數:★
現在有很多製造商都在賣掃地機械人,它非常有用,能為忙碌的我們分擔家務負擔。不過我們也很難理解為什麼掃地機械人有時候會反覆清掃某乙個地方。
假設有一款不會反覆清掃同乙個地方的機械人,它只能前後左右移動。舉個例子,如果第1 次向後移動,那麼連續移動3 次時,就會有以下9 種情況( 圖6 )。又因為第1 次移動可以是前後左右4 種情況,所以移動3 次時全部路徑有9×4 = 36 種。
※ 最初的位置用0 表示,其後的移動位置用數字表示。
問題:求這個機械人移動12 次時,有多少種移動路徑?
q2:初級
解決簡單問題體會演算法效果
難度係數:★★
「六度空間理論」非常有名。大概的意思是1 個人只需要通過6 個中間人就可以和世界上任何1 個人產生間接聯絡。本題將試著找出數字的好友(這裡並不考慮親密指數)。
假設擁有同樣約數(不包括1)的數字互為「好友」,也就是說,如果兩個數字的最大公約數不是1,那麼稱這兩個數互為好友。
從1~n 中任意選取乙個「合數」,求從它開始,要經歷幾層好友,才能和其他所有的數產生聯絡(所謂的「合數」是指「有除1 以及自身以外的約數的自然數」)。
舉個例子,n = 10 時,1~10 的合數是4、6、8、9、10 這5 個。
如果選取的是10,那麼10 的好友數字就是公約數為2 的4、6、8這3 個。而9 是6 的好友數字(公約數為3),所以10 只需要經過2 層就可以和9 產生聯絡(圖5 )。如果選取的是6,則只需經過1 層就可以聯絡到4、8、9、10 這些數字。因此n = 10 時,無論最初選取的合數是什麼,最多經過2 層就可以與其他所有數產生聯絡。
問題:求從1~n 中選取7 個合數時,最多經過6 層就可以與其他所有數產生聯絡的最小的n。
q3:中級
優化演算法實現高速處理
難度係數:★★★
可能大部分讀者都清楚,ipv4 中的ip 位址是二進位制的32 位數值。不過,這樣的數值對我們人類而言可讀性比較差,所以我們通常會以8 位為1 組分割,用類似192.168.1.2 這種十進位制數來表示它( 圖12 )。
這裡,我們思考一下十進位制數0~9 這10 個數字各出現1 次的ip 位址(像正常情況一樣,省略每組數字首位的0。也就是說,不能像192.168.001.002 這樣表示,而要像192.168.1.2 這樣來表示)
q4:高階
改變思路讓程式速度更快
難度係數:★★★★
回想起學生時期調座位的時候,我們的心裡總是會小鹿亂撞。想必很多人都對誰會坐自己旁邊這件事莫名地激動吧?
這裡我們考慮一種「前後左右的座位上一定都是異性」的座次安排。也就是說,像圖26 右側那樣,前後左右都是同性的座次安排是不符合要求的(男生用藍色表示,女生用灰色表示)。
問題:假設有乙個男生和女生分別有15 人的班級,要像圖26 那樣,排出乙個6×5的座次。求滿足上述條件的座次安排共多少種(前後或者左右映象的座次也看作不同的安排。另外,這裡不在意具體某個學生坐**,只看男生和女生的座次安排)?
答案q1-q4
q1答案
324932種。
q2答案
55滿足條件的組合為:
[4, 26, 39, 33, 55, 35, 49]
q3答案
8個。q4答案
13374192種。
程式設計師的最大挑戰
我思考越深就越堅信,如今的程式設計師的最大挑戰是沒有時間學習新知識。當在學校時,人們都有大量的時間來學習新工具和新技術,但一旦完成學業,有了全職工作,我們就拿不出足夠的時間來學習新東西了。而我們這個行業的變化卻是日新月異,對於乙個職業程式設計師,每週至少有40小時 真正 工作時間,完全沒有時間和精力...
程式設計師的演算法趣題Perl版 (二)
竟然一月一更。第四題 假設一根木棒n厘公尺,需要切分為一厘公尺長的木棒,每根木棒只可以乙個人切,木棒切成兩根可以兩個人切 求 n厘公尺長木棒,m個人最少要切幾次,比如n 8,m 3,則需要切4次。perl 20170930 use strict sub cut elsif currentparts ...
程式設計師的演算法趣題 Q3翻牌
這裡有 100 張寫著數字 1 100 的牌,並按順序排列著。最開始所有牌都是背面朝上放置。某人從第 2 張牌開始,隔 1 張牌翻牌。然後第 2,4,6,100 張牌就會變成正面朝上。接下來,另乙個人從第 3 張牌開始,隔 2 張牌翻牌 原本背面朝上的,翻轉成正面朝上 原本正面朝上的,翻轉成背面上 ...