力扣 36.有效的數獨
阿新 • • 發佈:2022-03-10
36. 有效的數獨
請你判斷一個 9 x 9
的數獨是否有效。只需要 根據以下規則 ,驗證已經填入的數字是否有效即可。
- 數字
1-9
在每一行只能出現一次。 - 數字
1-9
在每一列只能出現一次。 - 數字
1-9
在每一個以粗實線分隔的3x3
宮內只能出現一次。(請參考示例圖)
注意:
- 一個有效的數獨(部分已被填充)不一定是可解的。
- 只需要根據以上規則,驗證已經填入的數字是否有效即可。
- 空白格用
'.'
表示。
示例 1:
輸入:board = [["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"]] 輸出:true
示例 2:
輸入:board = [["8","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"]] 輸出:false 解釋:除了第一行的第一個數字從 5 改為 8 以外,空格內其他數字均與 示例1 相同。 但由於位於左上角的 3x3 宮內有兩個 8 存在, 因此這個數獨是無效的。
官方
方法一:一次遍歷
有效的數獨滿足以下三個條件:
class Solution { public: bool isValidSudoku(vector<vector<char>>& board) { int rows[9][9]; int columns[9][9]; int subboxes[3][3][9]; memset(rows,0,sizeof(rows)); memset(columns,0,sizeof(columns)); memset(subboxes,0,sizeof(subboxes)); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { char c = board[i][j]; if (c != '.') { int index = c - '0' - 1; rows[i][index]++; columns[j][index]++; subboxes[i / 3][j / 3][index]++; if (rows[i][index] > 1 || columns[j][index] > 1 || subboxes[i / 3][j / 3][index] > 1) { return false; } } } } return true; } };
大神思路
與官方題解不一樣在
遍歷到每個數的時候,例如boar[i][j],我們判斷其是否滿足三個條件:
在第 i 個行中是否出現過
在第 j 個列中是否出現過
在第 j/3 + (i/3)*3個box中是否出現過.為什麼是j/3 + (i/3)*3呢?
關於從陣列下標到box序號的變換
重述一遍問題:給定i和j,如何判定board[i][j]在第幾個box呢?
顯然屬於第幾個box由i和j的組合唯一確定,例如board[2][2]一定是第0個box,board[4][7]一定是第5個box,可以畫出來看一下,但是規律在哪裡呢?
我們可以考慮一種簡單的情況: 一個3x9的矩陣,被分成3個3x3的box,如圖:
顯然每個數屬於哪個box就只取決於縱座標,縱座標為0/1/2的都屬於box[0],縱座標為3/4/5的都屬於box[1],縱座標為6/7/8的都屬於box[2].也就是j/3.
而對於9x9的矩陣,我們光根據j/3得到0/1/2還是不夠的,可能加上一個3的倍數,例如加0x3,表示本行的box,加1x3,表示在下一行的box,加2x3,表示在下兩行的box, 這裡的0/1/2怎麼來的?和j/3差不多同理,也就是i/3。
合併
利用大神處理subbox的思路 j/3 + (i/3)*3
優化一下subboxes[3][3][9]
變成二維
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
int rows[9][9];
int columns[9][9];
int subboxes[9][9];
memset(rows,0,sizeof(rows));
memset(columns,0,sizeof(columns));
memset(subboxes,0,sizeof(subboxes));
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
char c = board[i][j];
if (c != '.') {
int index = c - '0' - 1;
rows[i][index]++;
columns[j][index]++;
subboxes[j/3 + (i/3)*3][index]++;
if (rows[i][index] > 1 || columns[j][index] > 1 || subboxes[j/3 + (i/3)*3][index] > 1) {
return false;
}
}
}
}
return true;
}
};