文章出處

 在這個日新月異的互聯網時代中,但萬變不離其宗的是,“算法”是其重要基石。要編寫高效率的程序,就需要優化算法。無論開發工具如何進化,熟識并能靈活運用算法仍然是對程序員的基本要求。

這里為那些已經學習過排序、搜索等知名算法,并想要學習更多有趣的算法,進一步提升編程技巧的工程師們準備了四道數學謎題形式的問題。這四道趣題分青銅、黃金、鉑金,鉆石級別。

在挑戰之前,先介紹下問題的具體形式:

每個問題大致分為“答案”和“解析”兩部分。

請各位先通讀問題描述,并動手編寫程序嘗試解題。在這個過程中,具體的實現方法是其次,更重要的是思考“通過哪些步驟來實現才能夠解決問題”。

每個問題都有思路講解和源代碼示例。請留意自己編程時在處理速度、可讀性等方面進行的優化,和本文的源代碼示例有什么不同。如果事先看了思路講解和答案,就會失去解題的樂趣,所以這里建議大家先編程解題,再看講解。

為了大家更好的享受解題樂趣,把“答案”和“解析”放在了最后。

你準備好接招了嗎?

 

Q1:倔強青銅

嘗試用編程解決問題

 

難度系數:★

優秀的掃地機器人

(IQ:80    目標時間:20分鐘)

現在有很多制造商都在賣掃地機器人,它非常有用,能為忙碌的我們分擔家務負擔。不過我們也很難理解為什么掃地機器人有時候會反復清掃某一個地方。

假設有一款不會反復清掃同一個地方的機器人,它只能前后左右移動。舉個例子,如果第1 次向后移動,那么連續移動3 次時,就會有以下9 種情況(如圖 )。又因為第1 次移動可以是前后左右4 種情況,所以移動3 次時全部路徑有9×4 = 36 種。

※ 最初的位置用0 表示,其后的移動位置用數字表示。

(移動路徑事例)

問題:求這個機器人移動12 次時,有多少種移動路徑?

(ps:最初三次的移動方向很自由,從第四次開始,坐標有些方向就不能移動啦)

 

Q2:榮耀黃金

解決簡單問題體會算法效果

難度系數:★★

朋友的朋友也是朋友嗎

(IQ:90    目標時間:25分鐘)

“六度空間理論”非常有名。大概的意思是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 產生聯系(如圖 )。如果選取的是6,則只需經過1 層就可以聯系到4、8、9、10 這些數字。因此N = 10 時,無論最初選取的合數是什么,最多經過2 層就可以與其他所有數產生聯系。

(N=10的時候)

問題: 求從1~N 中選取7 個合數時,最多經過6 層就可以與其他所有數產生聯系的最小的N。

 

Q3:尊貴鉑金

優化算法實現高速處理

難度系數:★★★

優雅的IP 地址

(IQ:100    目標時間:30分鐘)

可能大部分讀者都清楚,IPv4 中的IP 地址是二進制的32 位數值。不過,這樣的數值對我們人類而言可讀性比較差,所以我們通常會以8 位為1 組分割,用類似192.168.1.2 這種十進制數來表示它。

 

 

(IP地址 IPv4)

這里,我們思考一下十進制數0~9 這10 個數字各出現1 次的IP 地址(像正常情況一樣,省略每組數字首位的0。也就是說,不能像192.168.001.002 這樣表示,而要像192.168.1.2 這樣來表示)。

 

問題: 求用二進制數表示上述形式的IP 地址時,能使二進制數左右對稱的IP 地址的個數(用二進制數表示時不省略0,用完整的32 位數表示)。 (ps:IPv4的IP地址用十進制表示時,以點號分割的各部分數字都在0~255這個范圍內。可以通過求“比特列為8位且左右對稱”的數值,并將其設置在以點號分割的各部分上來解題。)

 

Q4:永恒鉆石

改變思路讓程序速度更快

難度系數:★★★★

異性相鄰的座次安排

(IQ:130    目標時間:60分鐘)

回想起學生時期調座位的時候,我們的心里總是會小鹿亂撞。想必很多人都對誰會坐自己旁邊這件事莫名地激動吧?

這里我們考慮一種“前后左右的座位上一定都是異性”的座次安排。也就是說,像圖右側那樣,前后左右都是同性的座次安排是不符合要求的(男生用藍色表示,女生用灰色表示)。(座位安排示例)

問題: 假設有一個男生和女生分別有15 人的班級,要像圖26 那樣,排出一個6×5的座次。求滿足上述條件的座次安排共多少種(前后或者左右鏡像的座次也看作不同的安排。另外,這里不在意具體某個學生坐哪里,只看男生和女生的座次安排)? (ps:剪枝可以有效的縮小搜索范圍哦)

~~~~~~~~~~~~~~~~~~~~~~~~~華麗麗的分割線~~~~~~~~~~~~~~~~~~~~~~~~

令人激動的答案來啦~

Q1答案:324932

詳細解析:用坐標(0, 0) 表示最初的位置。從這個原點開始,避開已經走過的坐標,使機器人前進。用深度優先搜索就可以實現邏輯,如圖所示。

 

 

Q2答案:55(滿足條件的組合為:【4,26,39,55,35,49】)

詳細解析:要解決這個問題,首先要正確理解問題中出現的詞。首先是“合數”。

其次是“公約數”這個詞。小學的時候,我們就做過求最大公約數的題。公約數的意思就是“共同的約數”。這里,擁有共同約數的數字互為“好友”,那么就需要求最大公約數非1 的情況。

從1~N 中選取7 個合數,且“最多經過6 層”,那么可以得知,我們要找的是“由2 個數相乘得到的數字”的組合。這樣的話,乘法運算中的這2 個數就會成為公約數。

舉個例子,選出a~h 這些數。簡單地說就是,當7 個數字分別是以下的形式時,經過6 層就能與其他所有數產生聯系。

a × b, b× c, c× d, d × e, e × f, f× g, g ×h

※這里a~h 這些數字必須“互質”。

更進一步考慮,也可以像本題中的例子一樣,把第1 個數字設置成“平方數”(即4),也就是說變成下面這樣的組合更好。

a × a, a × b, b × c, c × d, d × e, e × f, f × g

末尾如果同樣設置成平方數就會變得更小,也就是變成下面這樣的組合。

 a × a, a × b, b × c, c × d, d × e, e × f, f × f 

 用Ruby 可以如圖實現。

 

Q3答案:8個
詳細解析:按照題意,用十進制數表示時要使用0~9 這10 個數字各1 次,那么最高位是除0 以外的9 種情況,而其他各個數位可分別使用0~9 這10個數字各1 次,其排列組合一共9!(9 的階乘)種,所以總共要遍歷9×9! 種,也就是3265920 種情況。

要想求左右對稱的二進制數,可以通過把16 位的二進制數逆序排列,并將結果與該16 位的二進制數本身拼合,即生成32 位數來求得。因為是16 位,所以全量搜索時只需要遍歷65536 種情況即可。

然后,把這個二進制數轉換成十進制數,分別使用0~9 這10 個數字各1 次即可。

 

用Ruby 實現時,代碼如圖 所示。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()