1. 程式人生 > >我敢打賭,這是98%的程式設計師都想挑戰的演算法趣題!

我敢打賭,這是98%的程式設計師都想挑戰的演算法趣題!

計算機的世界每天都在發生著深刻的變化。新作業系統的釋出、CPU效能的提升、智慧手機和平板電腦的流行、儲存介質的變化、雲的普及……這樣的變化數不勝數。

在這樣日新月異的時代中,“演算法”是不變的重要基石。要編寫高效率的程式,就需要優化演算法。無論開發工具如何進化,熟識並能靈活運用演算法仍然是對程式設計師的基本要求。

本文為那些已經學習過排序、搜尋等知名演算法,並想要學習更多有趣的演算法,進一步提升程式設計技巧的工程師準備了四道數學謎題形式的問題。這四道趣題分入門、初級、中級、高階,四種級別。

我敢賭,這是100%的程式設計師都想挑戰的四道有【等級區別】演算法趣題。

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

每個問題大致分為“問題”和“詳解”兩部分。

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

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

準備好了嗎?我們開始答題吧!

Q1:入門-嘗試用程式設計解決問題

(難度係數:★)
優秀的掃地機器人(IQ:80 目標時間:20分鐘)

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

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

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

這裡寫圖片描述

問題:

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

這裡寫圖片描述

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 產生聯絡(圖5 )。如果選取的是6,則只需經過1 層就可以聯絡到4、8、9、10 這些數字。因此N = 10 時,無論最初選取的合數是什麼,最多經過2 層就可以與其他所有數產生聯絡。

這裡寫圖片描述

問題:

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

Q3:中級-優化演算法實現高速處理

難度係數:★★★
優雅的IP 地址(IQ:100 目標時間:30分鐘)

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

這裡寫圖片描述

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

問題:

求用二進位制數表示上述形式的IP 地址時,能使二進位制數左右對稱的IP 地址的個數(用二進位制數表示時不省略0,用完整的32 位數表示)。

這裡寫圖片描述

Q4:高階-改變思路讓程式速度更快

難度係數:★★★★
異性相鄰的座次安排(IQ:130 目標時間:60分鐘)

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

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

這裡寫圖片描述

問題:

假設有一個男生和女生分別有15 人的班級,要像圖26 那樣,排出一個6×5的座次。求滿足上述條件的座次安排共多少種(前後或者左右映象的座次也看作不同的安排。另外,這裡不在意具體某個學生坐哪裡,只看男生和女生的座次安排)?

這裡寫圖片描述

答案及解析Q1-Q4

Q1解題思路

用座標(0, 0) 表示最初的位置。從這個原點開始,避開已經走過的座標,使機器人前進。用深度優先搜尋就可以實現邏輯,如程式碼清單08.01 所示。

這裡寫圖片描述

Q1答案

324932種。

Q2解題思路

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

這裡寫圖片描述

其次是“公約數”這個詞。小學的時候,我們就做過求最大公約數的題。公約數的意思就是“共同的約數”。這裡,擁有共同約數的數字互為“好友”,那麼就需要求最大公約數非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 這些數字必須“互質”。

這裡寫圖片描述

Point!
更進一步考慮,也可以像本題中的例子一樣,把第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 可以像程式碼清單19.01 這樣實現。

這裡寫圖片描述

這裡寫圖片描述

Q2答案

55
滿足條件的組合為:
[4, 26, 39, 33, 55, 35, 49]

Q3解題思路

按照題意,用十進位制數表示時要使用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 實現時,程式碼如程式碼清單40.01 所示。

這裡寫圖片描述

執行程式可得到正確答案“8”,因而符合條件的IP 地址有8 個,如表4 所示。

這裡寫圖片描述

Point!
用十進位制數表示的時候,如果以點號分割的各部分左右對稱,那麼整體也就左右對稱,因而只需要調查0~255這些數對應的二進位制數中左右對稱的數就可以了。也就是說,A.B.C.D 這種形式中,A 要和D 對稱,B 要和C 對稱。

下面我們試著找出A~D 的各種組合中,0~9 這10 個數字各使用1次的組合。每組(A, D),( B, C)生成的IP地址有8種情況,所以用組合數乘以8 就可以求出結果。

用Ruby 實現時,程式碼如程式碼清單40.02 所示。

這裡寫圖片描述

Q3答案

8個。

Q4解題思路

如果完全按照問題描述實現,只需要遍歷30 個座位中15 個男生的座次,滿足條件就OK 了。如果不考慮可擴充套件性、處理速度等,只需要把不符合條件的情況排除就可以了,並不是很難。

這裡,我們事先準備好要排除的座次安排,統計不在這個範圍內的座次安排即可。用Ruby 實現時,如程式碼清單68.01 所示。

這裡寫圖片描述

要想改善處理速度,就要考慮“如何縮小搜尋範圍”。基本的辦法不外乎“剪枝”和“記憶體化”。

這裡,我們事先準備前2 排的座次安排,然後生成下一排可能的安排,並遞迴地搜尋下去。同時,把已經搜尋過的結果儲存到記憶體中,避免重複搜尋(程式碼清單68.02)。

這裡寫圖片描述

上面這個程式可以在2 秒左右求出正確答案。

這裡寫圖片描述

Q4答案

13374192種。

最後介紹一下文中出場人物:

這裡寫圖片描述

相關書推薦

這裡寫圖片描述

プログラマ脳を鍛える數學パズル シンプルで高速なコードが書けるようになる70問

作者:增井敏克

1979年生於奈良,畢業於大阪府立大學研究生院。增井IT工程師事務所代表、註冊工程師(資訊工程學方向)。
從事旨在“將商務、數學和IT結合以正確、高效使用計算機”的技能提升指導、軟體開發以及資訊保安諮詢等工作。
掌握C/C++、C#、Java、PHP和Ruby等20多種程式語言。
著作有《在家就能學會的安全基礎》等。目前在面向IT工程師提供業務技能評估服務的平臺CodeIQ上負責人氣欄目“每週演算法”的出題和評審工作。

譯者:絕雲

畢業於清華軟院。 曾在日本創意公司KAYAC從事即時通訊軟體和手遊的開發工作,現供職於螞蟻金服,專攻資料視覺化方向。
譯作有《圖解簡單演算法》《自制編譯器》等,曾參與《像外行一樣思考,像專家一樣實踐(修訂版)》的審校。

定價:55.00元

  • 2016日本IT技術圖書大賞獲獎作品
  • 日本人氣演算法訓練欄目“每週演算法”精選輯錄
  • 140,000程式設計師挑戰過的演算法PUZZLE

為什麼要讀這本書?

本書是一本解謎式的趣味演算法書,包含69道數學謎題形式的問題。從實際應用出發,通過趣味謎題的解謎過程,引導讀者在愉悅中提升思維能力、掌握演算法精髓。

此外,本書作者在謎題解答上,通過演算法的關鍵原理講解,從思維細節入手,發掘啟發性演算法新解,並輔以Ruby、JavaScript等不同語言編寫的原始碼示例,使讀者在演算法思維與程式設計實踐的分合之間,切實提高程式設計能力。

目錄
第1章 入門篇★嘗試用程式設計解決問題
二進位制和十進位制
Q01 迴文十進位制數
Q02 數列的四則運算
Q03 翻牌
Q04 切分木棒
Q05 還在用現金支付嗎
Q06 (改版)考拉茲猜想
Q07 日期的二進位制轉換
Q08 優秀的掃地機器人
Q09 落單的男女
Q10 輪盤的最大值

第2章 初級篇★解決簡單問題 體會演算法效果
價效比意識
Q11 斐波那契數列
Q12 平方根數字
Q13 有多少種滿足字母算式的解法
Q14 世界盃參賽國的國名接龍
Q15 走樓梯
Q16 3根繩子折成四邊形
Q17 挑戰30人31足
Q18 水果酥餅日
Q19 朋友的朋友也是朋友嗎
Q20 受難立面魔方陣
Q21 異或運算三角形
Q22 不纏繞的紙杯電話
Q23 二十一點通吃
Q24 完美的三振出局
Q25 鞋帶的時髦系法
Q26 高效的立體停車場
Q27 禁止右轉也沒關係嗎
Q28 社團活動的最優分配方案
Q29 合成電阻的黃金分割比
Q30 用插線板製作章魚腳狀線路

第3章 中級篇★★★優化演算法 實現高速處理
時間複雜度記法和計算量
Q31 計算最短路徑
Q32 榻榻米的鋪法
Q33 飛車與角行的棋步
Q34 會有幾次命中註定的相遇
Q35 0和7的迴文數
Q36 翻轉骰子
Q37 翻轉7段碼
Q38 填充白色
Q39 反覆排序
Q40 優雅的IP 地址
Q41 只用1個數字表示1234
Q42 將牌洗為逆序
Q43 讓玻璃杯水量減半
Q44 質數矩陣
Q45 排序交換次數的最少化
Q46 唯一的○×序列
Q47 格雷碼迴圈
Q48 翻轉得到交錯排列
Q49 欲速則不達
Q50 完美洗牌
Q51 同時結束的沙漏
Q52 糖果惡作劇
Q53 同數包夾
Q54 偷懶的算盤
Q55 平分蛋糕

第4章 高階篇★★★★改變思路 讓程式速度更快
編碼風格
Q56 鬼腳圖中的橫線
Q57 最快的聯絡網
Q58 丟手絹遊戲中的總移動距離
Q59 合併單元格的方式
Q60 分割為同樣大小
Q61 不交叉, 一筆畫下去
Q62 日曆的最大矩形
Q63 迷宮會合
Q64 麻煩的投接球
Q65 圖形的一筆畫
Q66 設計填字遊戲
Q67 不挨著坐是一種禮節嗎
Q68 異性相鄰的座次安排
Q69 藍白歌會

本週特價電子書