题目:
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.
The Sudoku board could be partially filled, where empty cells are filled with the character '.'
.
A partially filled sudoku which is valid.
Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.
注意到题目中说的,只要当前已经填充的数字是合法的就可以,不一定要这个数独是有解.(下面说的九宫格都是指3*3的网格)
因此只需要判断9*9网格的每一行、每一列、9个小九宫格是否合法。即如果在每一行、每一列、每个9个小九宫格内,某个数字重复出现了,当前数独就是不合法的
构造一个检验函数,判断是否数字重复,重复返回false, 不重复填入数组;
然后遍历九宫格,逐一检查非空的元素。
Attention:
1. 假设vector<char> 存储每一行,vector<vector<char>> 存储九行。按照输入数字的习惯
2. Board[i][j]对应第i行,第J列,第 i/3 *3 + j/3个小九宫格(九宫格按照从0开始编号)
3. 数组本来就是指针,不应该用&; bool checkValid(int &vec[], int val) 错误的!There shall be no references to references, no arrays of references, and no pointers to references.
复杂度:时间O(N^2)
AC Code:
class Solution { public: bool isValidSudoku(vector<vector<char> > &board) { //证明一个数独是否有效,可能部分填充。 //假设vector<char> 存储每一行,vector<vector<char>> 存储九行。按照输入数字的习惯 //Attention: Board[i][j]对应第i行,第J列,第 i/3 *3 + j/3个小九宫格(九宫格按照从0开始编号) //Attention:There shall be no references to references, no arrays of references, and no pointers to references. //数组本来就是指针,不应该用&; bool checkValid(int &vec[], int val) 错误的! //数组大小定义为10,因为输入为'1'~'9',转成int型后('1'-'0'),将存储在数组A[1]~A[9],第一位A[0]为空。 int rowValid[10] = {0}; //判断每行是否合法 int columnValid[9][10] = {0}; //九列 判断每列是否合法 int subBoardValid[9][10] = {0}; //九个小九宫格 判断每个小九宫格是否合法 需要把所有数据填进去 for(int i = 0; i < 9; i++) { //每行需要重新置0 memset(rowValid, 0, sizeof(rowValid)); for(int j = 0; j < 9; j++) { if(board[i][j] != '.') { if(!checkValid(rowValid, board[i][j] - '0') || !checkValid(columnValid[j], board[i][j] - '0')|| !checkValid(subBoardValid[i/3*3 + j/3], board[i][j] - '0')) return false; } } } return true; } //检查填入数字是否重复,不重复则填入 bool checkValid(int vec[], int val) { if(vec[val] == 1) { return false; } else { vec[val] = 1; return true; } } };
针对上面的算法,还可以优化空间。上面的算法中,在双重循环时,我们默认了第一重循环表示矩阵的行、第二重循环表示矩阵的列。可以换一种思路:
class Solution { public: bool isValidSudoku(vector<vector<char> > &board) { int rowValid[10] = {0}; int columnValid[10] = {0}; int subBoardValid[10] = {0}; for(int i = 0; i < 9; i++) { memset(rowValid, 0, sizeof(rowValid)); memset(columnValid, 0, sizeof(columnValid)); memset(subBoardValid, 0, sizeof(subBoardValid)); for(int j = 0; j < 9; j++) { if(!checkValid(rowValid, board[i][j] - '0') || !checkValid(columnValid, board[j][i] - '0')|| !checkValid(subBoardValid, board[3*(i/3) + j/3][3*(i%3) + j%3] - '0')) return false; } } return true; } bool checkValid(int vec[], int val) { if(val < 0) return true; // val对应空字符。 '.'对应46 '0'对应48 if(vec[val] == 1) { return false; } else { vec[val] = 1; return true; } } };