Dimple在左耳聽風ARTS打卡(二十)

今天的內容乾貨滿滿,還煩請大家仔細觀看。首先真是一個值得紀念的日子,歷時5個月,終於把《Head First設計模式》這本書給二刷完成了。想起第一次看的時候,也是做了各種目標,竟然沒能堅持到最後。

年後回來,下定決心要把書看完,並且輸出設計模式系列文章,這次我做到了。今天終於把書看完,實踐部分還需要文章輸出,估計也就是這幾天的事,努力成長吧。

寫完今天的算法我就有點後悔,這個難度略大,完全可以用一整篇文章來描述過程,尷尬尷尬。以後我注意下,遇到類似的算法,單獨寫一個系列出來即可。很多號主,都有專門的力扣刷題系列,看來我也可以加一個這個系列,並把代碼共享出來了,我儘快執行起來。

Algorithm LeetCode算法

解數獨
(https://leetcode-cn.com/problems/sudoku-solver/)

題目描述:編寫一個程序,通過已填充的空格來解決數獨問題。

一個數獨的解法需遵循如下規則:

  1. 數字 1-9 在每一行只能出現一次。

  2. 數字 1-9 在每一列只能出現一次。

  3. 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。

空白格用‘.’表示

123456789
53

7



6

195



98



6
8


6


3
4

8
3

1
7


2


6

6



28



419

5




8

79


解題思路: 我這裏採用直接搜索的方式,寫一個輔助函數檢查三條規則:

private static boolean isValid(char[][] board, int i, int j, char num) {    // 先判斷行,列固定不變,查看是否有衝突    for (int row = 0; row < 9; row++) {        if (board[row][j] == num) {            return false;        }    }    // 再判斷列,行固定不變,查看是否有衝突    for (int col = 0; col < 9; col++) {        if (board[i][col] == num) {            return false;        }    }    // 9宮格是否有衝突    for (int row = i / 3 * 3; row < i / 3 * 3 + 3; row++) {        for (int col = j / 3 * 3; col < j / 3 * 3 + 3; col++) {            if (board[row][col] == num) {                return false;            }        }    }    return true;}
    // 先判斷行,列固定不變,查看是否有衝突
    for (int row = 0; row < 9; row++) {
        if (board[row][j] == num) {
            return false;
        }
    }
    // 再判斷列,行固定不變,查看是否有衝突
    for (int col = 0; col < 9; col++) {
        if (board[i][col] == num) {
            return false;
        }
    }
    // 9宮格是否有衝突
    for (int row = i / 3 * 3; row < i / 3 * 3 + 3; row++) {
        for (int col = j / 3 * 3; col < j / 3 * 3 + 3; col++) {
            if (board[row][col] == num) {
                return false;
            }
        }
    }
    return true;
}
 

因爲是一個九宮格,我們傳入的是一個二維數組,一行裏面包含9個位置,總共是9行,組成的81個位置。

所以,還需要通過位置依次來填充。從(0,0)到(8,8),如果是".",說明該位置沒有被填充,則可以查找數字並填充進去,否則繼續查找下一個位置。

如果填充失敗,那麼我們需要回溯。將原來嘗試填充的地方改回來。

遞歸直到數獨被填充完成。

private static boolean searchRes(char[][] board) {    for (int i = 0; i < board.length; i++) {        for (int j = 0; j < board[0].length; j++) {            if (board[i][j] != '.') {                continue;            }            for (char num = '1'; num <= '9'; num++) {//嘗試                if (!isValid(board, i, j, num)) {                    continue;                }                board[i][j] = num;                boolean result = searchRes(board);                if (result) {                    return true;                } else {                    board[i][j] = '.';//回退之前的狀態,本輪搜索失敗,回退的時候也是遞歸的                }            }            return false;        }    }    return true;}
    for (int i = 0; i < board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            if (board[i][j] != '.') {
                continue;
            }
            for (char num = '1'; num <= '9'; num++) {//嘗試
                if (!isValid(board, i, j, num)) {
                    continue;
                }
                board[i][j] = num;
                boolean result = searchRes(board);
                if (result) {
                    return true;
                } else {
                    board[i][j] = '.';//回退之前的狀態,本輪搜索失敗,回退的時候也是遞歸的
                }
            }
            return false;
        }
    }
    return true;
}

好啦,就這樣把解數獨的問題完成了。可能大家還不知道如何去傳入這個二維數組驗證,這次我就寫下main函數吧。這裏僅給出如何傳入二維數組的過程,至於如何打印結果,大家自己積極發揮下噢

public static void main(String[] args) {    char[][] board = new char[][]{        {'5', '3', '.', '.', '7', '.', '.', '.', '.'},        {'6', '.', '.', '1', '9', '5', '.', '.', '.'},        {'.', '9', '8', '.', '.', '.', '.', '6', '.'},        {'8', '.', '.', '.', '6', '.', '.', '.', '3'},        {'4', '.', '.', '8', '.', '3', '.', '.', '1'},        {'7', '.', '.', '.', '2', '.', '.', '.', '6'},        {'.', '6', '.', '.', '.', '.', '2', '8', '.'},        {'.', '.', '.', '4', '1', '9', '.', '.', '5'},        {'.', '.', '.', '.', '8', '.', '.', '7', '9'}    };    searchRes(board);}
    char[][] board = new char[][]{
        {'5''3''.''.''7''.''.''.''.'},
        {'6''.''.''1''9''5''.''.''.'},
        {'.''9''8''.''.''.''.''6''.'},
        {'8''.''.''.''6''.''.''.''3'},
        {'4''.''.''8''.''3''.''.''1'},
        {'7''.''.''.''2''.''.''.''6'},
        {'.''6''.''.''.''.''2''8''.'},
        {'.''.''.''4''1''9''.''.''5'},
        {'.''.''.''.''8''.''.''7''9'}
    };

    searchRes(board);
}

Review 閱讀並點評至少一篇英文文章

How to Implement the New In-App Update Feature to Your Android App
(https://medium.com/better-programming/add-in-app-updates-to-your-android-app-in-just-5-lines-of-code-655440abc8e8)

《如何爲Android應用程序實施新的應用程序內更新功能》看到這個標題,其實並沒有引起我特別大的關注,但是摘要裏面有顯示,他能讓Android的應用內更新,通過5行代碼就能夠搞定,還是讓我震驚了。

現在,Android的Play核心庫有一個應用內更新的功能,它引入了一個新的請求流,以提示活躍用戶更新您的應用。但是,這些代碼太多了,倘若將所有代碼都添加進應用,那將是一個很累人的事情。

但是,這位作者就很有開源和分享的精神,他自己開發了一個應用內更新功能的庫,將整個內容減少到5行代碼。具體怎麼做,文中有描述,這裏我就不進行贅述了。

給我的感慨就是,每一位開發者,真的需要有一顆對技術充滿狂熱的心,這樣才能更好地爲軟件開發做更多的事情,做更多的貢獻。還記得Android 6.0權限剛出來的時候,大家都是按部就班地去執行,但是很多人就想到了用封裝庫的辦法,把繁雜的代碼簡化,提高了很多開發者的工作效率,很多人因此受益。

所以,我們爲什麼不也去試試看呢。前段時間學習微服務,猿天地的尹吉歡大哥在書中也介紹了自己的一個開源庫,用在微服務的配置裏,很是好用。他也說了,技術人都需要有一顆開源分享的心,是對自己技術的肯定,也是對社區的貢獻。

所以,等着Dimple的讀者們的給力表現,我自己也將更加努力。按照上面說的,首先去嘗試下力扣上的算法題分享。

Tip 一個技術技巧

昨天,和一位小兄die聊天,聊到Linux的tail命令,這個命令是我平時在運維機器上經常使用的,所以還是有點心得,但苦於沒有很好的總結。剛好這次趕上了。

一、tail命令語法

tail [ -f ] [ -c Number | -n Number | -m Number | -b Number | -k Number ] [ File ]

參數解釋:

-f 該參數用於監視File文件增長。

-c Number 從 Number 字節位置讀取指定文件

-n Number 從 Number 行位置讀取指定文件。

-m Number 從 Number 多字節字符位置讀取指定文件,比方你的文件假設包括中文字,假
設指定-c參數,可能導致截斷,但使用-m則會避免該問題。

-b Number 從 Number 表示的512字節塊位置讀取指定文件。

-k Number 從 Number 表示的1KB塊位置讀取指定文件。
File 指定操作的目標文件名稱

上述命令中,都涉及到number,假設不指定,默認顯示10行。Number前面可使用正負號,表示該偏移從頂部還是從尾部開始計算。

tail可運行文件一般在/usr/bin/以下。

二、tail命令使用方法演示例子

1、tail -f filename

說明:監視filename文件的尾部內容(默認10行,相當於增加參數 -n 10),刷新顯示在屏幕上。退出,按下CTRL+C。

2、tail -n 20 filename

說明:顯示filename最後20行。

Share 一篇有觀點和思考的技術文章

設計模式走起來。

公衆號地址:
設計模式之命令模式(三)

640?wx_fmt=jpeg
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章