ARTS 是陳浩(網名左耳朵耗子)在極客時間專欄裏發起的一個活動,目的是經過分享的方式來堅持學習。程序員
每人每週寫一個 ARTS:Algorithm 是一道算法題,Review 是讀一篇英文文章,Technique/Tips 是分享一個小技術,Share 是分享一個觀點。
這周的 ARTS 你將看到:面試
本週的算法題是網紅面試題 N皇后問題: LeetCode 51 N-Queens.算法
這是一道很是經典的使用 回溯 + 剪支 的搜索類題目, 這道題雖然是 hard 難度, 但我感受最可貴地方在於想到使用深度優先搜索的方法.編程
下面是代碼, 思路詳見註釋.架構
func solveNQueens(n int) [][]string { ans := make([][]int, 0) // 下面是回溯記憶操做, 用於剪支 // 由於每次回溯都按行 row 從上到下進行, 所以同一行的皇后互斥已經在回溯流程被排除了 // 只須要考慮列和兩種對角線 col := make(map[int]struct{}, 0) // 表明列中是否已存在皇后 pie := make(map[int]struct{}, 0) // 表明撇(右上到左下)是否已存在皇后 na := make(map[int]struct{}, 0) // 表明捺(左上到右下)是否已存在皇后 queens := make([]int, 0) // i 表示搜索進行到第 i 行 var dfs func(i int) dfs = func(i int) { if i == n { // 這裏必須對 queens 進行深拷貝, 不然後續回溯會影響 ans 中的結果 tmp := make([]int, len(queens)) copy(tmp, queens) ans = append(ans, tmp) } for j := 0; j < n; j++ { _, a := col[j]; _, b := pie[i+j]; _, c := na[i-j] // 剪支 if !a && !b && !c { col[j], pie[i+j], na[i-j] = struct{}{}, struct{}{}, struct{}{} queens = append(queens, j) dfs(i+1) delete(col, j); delete(pie, i+j); delete(na, i-j) // 由於底層數據沒有變, 因此必須刪除本次添加的元素, 後續回溯才能正常使用 queens queens = queens[:len(queens)-1] } } } dfs(0) return genMetric(ans, n) } func genMetric(ans [][]int, n int) [][]string { ret := make([][]string, 0) s := "" for i := 0; i < n; i++ { s += "." } for _, queens := range ans { metric := make([]string, 0) for _, q := range queens { l := []byte(s) l[q] = 'Q' metric = append(metric, string(l)) } ret = append(ret, metric) } return ret }
本週的文章推薦是關於軟件架構中的過分設計的: 十個軟件系統過分設計的例子.app
做者用他十五年的工做經驗擔保, 絕對不存在收斂的業務. 業務這玩意兒只可能愈來愈多, 愈來愈發散. 由於增加就是業務的本質特徵, 不能怪業務方.工具
最好記住一點, 業務方永遠是爸爸.學習
若是隻是單純的經過重用以前的邏輯來構建新的業務邏輯, 即, 在已有的公共邏輯基礎上進行橫向的擴展. 那麼隨着業務功能的增長, 系統會變得愈來愈複雜, 知道不可維護.設計
因此, 在依賴公共邏輯進行功能的橫向擴展以前, 先對公共部分的邏輯作細分(或者叫縱向劃分).code
程序員有時候會被寫出優秀的抽象代碼的願望衝昏了頭腦, 以致於爲了抽象而抽象, 下降了代碼的可讀性卻並無帶來多少可維護性.
有時候, 錯誤的抽象還不如重複的代碼堆疊.
對依賴庫的封裝必定要考慮更換依賴實現的可能, 同時不要在封裝中摻雜具體的業務邏輯.
給每種對象都抽象除一個接口(或者抽象類), 或者盲目應用某些看似高級的語法特性. 無腦應用那些高級的軟件設計原則, 這樣的作法並不可取. 若是隻是一個很是簡單的小邏輯, 之後複用的可能幾乎沒有, 那麼這種狀況仍是把那些原則和方法忘掉吧. 這些概念不是普通的小工具, 只有場景合適才能發揮做用.
這點有些相似誤區五種的意思, 沒有場景空談使用時沒有意義的.
做者列出的一些 "ity" 的例子, Configurability, Security, Scalability, Maintainability, Extensibility.
落實這些概念以前, 必定要想一想目前系統的真實場景.
輪子造出來並非重點, 後期維護的成本也很是高, 決定作這件事情以前必定要想好.
重構是必然的結果, 不存在動不了的代碼.
優秀的系統須要優秀的開發者和時間, 並且不管多優秀的開發者的開發速度都是有極限的, 又快又好是不存在的.
本週沒有技巧...
理論學習只能提高認知, 只有實踐才能出真知.