Arts 第四周(4/8 ~ 4/14)
ARTS是什么?
Algorithm:每周至少做一個leetcode的算法題;
Review:閱讀并點評至少一篇英文技術文章;
Tip:學習至少一個技術技巧;
Share:分享一篇有觀點和思考的技術文章。
Algorithm
題目:
LC 37. Sudoku Solver
解答:
與 N 皇后問題一樣,數獨問題也是考察回溯與深度優先搜索的經典問題,這樣的問題難點在于優化,也就是如何進行剪枝,何時進行剪枝。根據題目描述,我們需要保證橫、豎以及 3X3 的方格內的所有數字不重復,這樣我們可以通過用 boolean 標記數組來實現對橫、豎、方塊的驗證,只要之前填的值有問題,就立刻返回 false,不然就填入符合要求的值,然后繼續遞歸,直到所有的空位都被填滿,這里有個點就是方塊的定位可以通過當前行列下標除以 3 來定位,例如 [2/3][1/3] 表示的就是左上角那塊空格。你也可以不使用標記數組,這樣在驗證的時候就需要多寫一層循環來逐一判斷,當然代碼會比較簡潔,但是在時間上面并不是特別的高效。
實現參考代碼:
public void solveSudoku(char[][] board) {boolean[][] rows = new boolean[9][9];boolean[][] cols = new boolean[9][9];boolean[][][] squares = new boolean[3][3][9];for (int r = 0; r < board.length; ++r) {for (int c = 0; c < board[0].length; ++c) {if (board[r][c] != '.') {rows[r][board[r][c] - '1'] = true;cols[c][board[r][c] - '1'] = true;squares[r/3][c/3][board[r][c] - '1'] = true;}}}helper(board, rows, cols, squares); }private boolean helper(char[][] board,boolean[][] rows,boolean[][] cols,boolean[][][] squares) {for (int r = 0; r < board.length; ++r) {for (int c = 0; c < board[0].length; ++c) {if (board[r][c] == '.') {for (char i = '1'; i <= '9'; ++i) {if (isValid(board, rows[r], cols[c], squares[r/3][c/3], i)) {board[r][c] = i;rows[r][i - '1'] = true;cols[c][i - '1'] = true;squares[r/3][c/3][i - '1'] = true;if (helper(board, rows, cols, squares)) {return true;} else {board[r][c] = '.';rows[r][i - '1'] = false;cols[c][i - '1'] = false;squares[r/3][c/3][i - '1'] = false;}} }return false;}}}return true; }private boolean isValid(char[][] board, boolean[] row, boolean[] col, boolean[] square, char c) {if (row[c - '1'] || col[c - '1'] || square[c - '1']) {return false;}return true; } 復制代碼Review
在 medium 上看到的一篇講關于如何 debug 的文章:
How Debugging Can Make You a Better Developer
一提到 debug,沒有人會喜歡,很有可能的是,你花費了數個小時,但是依然毫無收獲,即使你發現了問題,大多數情況下也是一些不起眼的小問題,例如參數傳錯,變量忘記賦值之類的,如果不花大塊的時間進行全面的深度總結的話,很難說能從中學到什么。文章中給出了 debug 的一些建議,是一些方向性的建議,如果能夠形成意識,相信會大大縮短 debug 的時間,提升開發效率:
-
首先了解框架系統,以及全局的設計
debug 難點不在于解決問題,而是在于尋找問題,定位問題,問題可能就是出在一個點上,而往往這個點并不在我們直覺所認為的那個地方上,不知道你有沒有過這樣的經歷,就是把自己寫的函數反復看了好幾遍,改了又改,但是依然沒找到問題,最后發現其實是調用函數的地方出現了問題,告訴自己下次一定要注意,但是往往下次還是會犯類似的問題。這樣低效的原因其實就是我們沒有從全局來看待問題,一直盯著一個地方看,并不是一個好的尋找策略,搜索一般都是從大到小,而且常常思考每個部分在整體當中扮演的角色以及功能,也是有助于我們理解整個系統的。只有當我們了解了這些全局的東西,才能夠更清晰地定位問題。
Always remember, you need a working knowledge of what the system is supposed to do, how it’s designed, and, in some cases, why it was designed that way. If you don’t understand some part of the system, that always seems to be where the problem is.
-
分離并縮小問題出現的范圍
上面說到如何定位問題,但是有時候是知道問題大概是什么,但是整個系統很龐大,類似的問題可能在多個地方出現,這時的策略就是分治,這里的分治是指分開來檢查,其實就是排除法了,主要的目的是縮小定位問題的范圍,當然這一步是建立在上一步的基礎之上的,只有當你了解了全局系統之后,才能更好的做分離
Always remember It’s hard for a bug to keep hiding when its hiding place keeps getting cut in half.
-
每次只改變一個地方
在 debug 的時候我們會有一些猜想,例如這幾個地方可能是出錯點,但是并不確定,需要驗證,這時我們最好是同時只改變一個地方,看問題有沒有得到解決,不然的話,多個地方同時被更改,問題解決了,你也不知道是哪出錯了,問題還是沒有找到,更糟糕的是你把之前好的代碼更改了,往后可能會有更多的問題。
Always remember you can always tell exactly which parameter had the effect if you make one change at a time. And if a change doesn’t seem to have an effect, back it out right away!
-
驗證你是不是真的解決了問題
有些時候我們定位到了問題,但是有可能并不只是這一個地方出錯,很有可能這個問題是多處出錯的結果;我們需要做的是測試在不同場景下的修復結果,如果把修復的代碼拿掉,就會產生問題,把修復的代碼加上,在任何的場景下,都不會有問題,這時我們才能說我們找到了并修補了 bug。
Always remember, If the system fails as it used to when you remove only the fix, only then you can be pretty sure the fix is indeed working.
-
對于解決的問題,記錄下來
我們總是在借鑒前輩的經驗,來節省自己的嘗試成本,前輩們犯過的錯,我們總結了,思考了,下次很大幾率不會犯同樣的錯,大大節省做事效率。同樣的,我們也要知道我們自己干過的事情,更細致一點就是是什么問題?什么時候犯的?在什么情況下犯的?如何解決的?作者給了幾個記錄點,可以參考,根據實際的項目情況增添或者刪減:
- Issue #
- Initiator (who logged the call)
- Initiator Extension or Phone #
- Date/Time Opened
- Summary Description
- Impact/Importance
- Type (of fault)
- Owner (of system)
- Current Status (open, in process, closed)
- Next Step
- Next Step Date
- Completion Date
- Resolution, development request # or link to vendor support request
“When debugging, novices insert corrective code; experts remove defective code.” - Richard Pattis
最后需要記住的是,debug 的過程其實是一個學習的機會,是一個讓自己成為更好的程序員的機會。成長的過程往往都不是很輕松,都會有痛苦相伴,但是值得慶幸的是,你可以從中學到不少你從未接觸,或者了解的比較少的東西,例如語言的特性,系統的設計理念,以及有用的開發工具等等,相信這些東西往后都會成為你職業技能上的寶貴財富。
Tip
看極客時間 趣談Linux操作系統 專欄,學到了幾個 Linux 命令,之前沒怎么了解,但是了解之后感覺是提升工作效率的利器:
-
export 命令僅在當前命令行的會話中生效,如果需要永久生效,要在 .bashrc 文件里面進行設定
-
ubuntu 系統下的軟件管家
安裝 -> $> apt-get install ...
搜索 -> $> apt-cache search ...
刪除 -> $> apt-get purge ...
配置文件 -> /etc/apt/sources.list -
后臺運行命令 nohup
$> nohup command >out.file 2>&1 &這里 “1” 表示文件描述符 1,表示標準輸出,“2” 表示文件描述符 2,意思是標準錯誤輸出,“2>&1” 表示標準輸出和錯誤輸出合并,合并到 out.file 里面
-
查看運行進程的命令 ps -ef
$> ps -ef | grep 關鍵字 | awk ‘{print $2}’ | xargs kill -9ps -ef 可以單獨運行,表示列出當前運行的程序,awk 可以很靈活地對文本進行處理,awk ‘{print $2}’ 是指第二列的內容,是運行程序的ID。我們可以通過 xargs 傳遞給 kill -9,也就是發給這個運行的程序一個信號,讓它關閉。
-
服務運行命令 systemctl
$> systemctl start mysql
$> systemctl enable mysql
$> systemctl stop mysql之所以成為服務并且能夠開機啟動,是因為在 /lib/systemd/system 目錄下,創建了一個 XXX.service 的配置文件,從而成為一個服務
Share
看了極客時間上面的 10X程序員工作法 專欄,結合自己現在的工作情況,有些小感悟,分享在這里,也是希望得到大神們的指點,也希望和志同道合的朋友們相互認識,相互成長。
寫項目代碼之前必須要做的事
轉載于:https://juejin.im/post/5ca68d21f265da30c7042c34
總結
以上是生活随笔為你收集整理的Arts 第四周(4/8 ~ 4/14)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop HA 双namenode搭
- 下一篇: 王者荣耀孙悟空技能顺序怎么放 《王者》在