LeetCode - 有效的數獨

GitHub:https://github.com/biezhihua/LeetCode

題目

判斷一個數獨是否有效,根據:Sudoku Puzzles - The Rules。

數獨部分填了數字,空的部分用 ‘.’ 表示。

這裏寫圖片描述

一個部分填充是有效的數獨。

說明:
一個有效的數獨(填了一部分的)不一定是可解的,只要已經填的數字是有效的即可。

解法

https://github.com/biezhihua/LeetCode

這道題我沒有解出更高效的方法,所以參考了:http://www.cnblogs.com/grandyang/p/4421217.html

這道題讓我們驗證一個方陣是否爲數獨矩陣,判斷標準是看各行各列是否有重複數字,以及每個小的3x3的小方陣裏面是否有重複數字,如果都無重複,則當前矩陣是數獨矩陣,但不代表待數獨矩陣有解,只是單純的判斷當前未填完的矩陣是否是數獨矩陣。那麼根據數獨矩陣的定義,我們在遍歷每個數字的時候,就看看包含當前位置的行和列以及3x3小方陣中是否已經出現該數字,那麼我們需要三個標誌矩陣,分別記錄各行,各列,各小方陣是否出現某個數字,其中行和列標誌下標很好對應,就是小方陣的下標需要稍稍轉換一下,

雖然這個博主說的很簡單,但是思考起來還確實需要仔細思考一下。

首先是申請了三個二維數組rawFlagcolFlag以及cellFlag

rawFalg用於代表某行中是否出現過數字X,舉個例子:

假設:i = 0;c = 8;
那麼rawFlag[i][c] = true的含義爲:在第0行中,出現過數字8。

假設:i = 8; c = 1;
那麼rawFlag[i][c] = true的含義爲:在第8行中,出現過數字1。

明白了rawFlag[][]的含義,那麼colFlag[][]的含義也就容易理解了,
用於代表某列中是否出現過數字X,繼續舉個例子:

假設:i = 0;c = 8;
那麼colFlag[i][c] = true的含義爲:在第0列中,出現過數字8。

假設:i = 8; c = 1;
那麼colFlag[i][c] = true的含義爲:在第8列中,出現過數字1。

那麼以此類推cellFlag[][]的含義爲某個3x3方陣中是否出現過數字X
此外,假設左上角是第一個方陣,右上角是第三個方陣,左下角是第六個方陣,右下角是第九個方陣。
舉個例子:

假設:i = 0;c = 8;
那麼cellFlag[i][c] = true的含義爲:在第0個方陣中,出現過數字8。

假設:i = 8; c = 1;
那麼cellFlag[i][c] = true的含義爲:在第8個方陣中,出現過數字1。

知道了上面這些,使用3 * (i / 3) + j / 3 (i代表行的增加、j代表列的增加)就可以根據當前的行列關係計算出當前處於第幾個方陣。


        0  1  2
        3  4  5
        6  7  8

另外,在標識數字存在的時候,還使用了算法 - 兩數之和中的技巧,使用下標標識數字。

@Test
public void test() {
    char[][] a = {{'.', '8', '7', '6', '5', '4', '3', '2', '1'}, {'2', '.', '.', '.', '.', '.', '.', '.', '.'}, {'3', '.', '.', '.', '.', '.', '.', '.', '.'}, {'4', '.', '.', '.', '.', '.', '.', '.', '.'}, {'5', '.', '.', '.', '.', '.', '.', '.', '.'}, {'6', '.', '.', '.', '.', '.', '.', '.', '.'}, {'7', '.', '.', '.', '.', '.', '.', '.', '.'}, {'8', '.', '.', '.', '.', '.', '.', '.', '.'}, {'9', '.', '.', '.', '.', '.', '.', '.', '.'}};
    Assert.assertEquals(true, isValidSudoku(a));
}

public boolean isValidSudoku(char[][] board) {

    boolean[][] rowFlag = new boolean[9][9];
    boolean[][] colFlag = new boolean[9][9];
    boolean[][] cellFlag = new boolean[9][9];

    for (int i = 0; i < 9; ++i) {
        for (int j = 0; j < 9; ++j) {
            if (board[i][j] >= '1' && board[i][j] <= '9') {
                int c = board[i][j] - '1';
                if (rowFlag[i][c] || colFlag[c][j] || cellFlag[3 * (i / 3) + j / 3][c]) return false;
                rowFlag[i][c] = true;
                colFlag[c][j] = true;
                cellFlag[3 * (i / 3) + j / 3][c] = true;
            }
        }
    }
    return true;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章