题目:
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.
思路:
先弄清楚题目的意思,题目不是要求我们将数独解出来,也不是判断数独是否有解,而是将判断数独是否合法的,所谓合法,是指每个数字都是1-9,而且每一行,每一列都没有数字重复。大家首先想到的肯定是两个fou循环,逐次判断每行或者每列是否满足。那么如何判断某一行是否有重复呢,如果每个元素都与前面的元素进行比较,将会花费O(n^2*(1+n)*n/2)=O(n^4)天啦,太浪费时间了。
当然我们可以用一个空间复杂度为O(n)的hash表来代替,这样,每次判断是否重复的时间为O(1),总时间为O(n^2)。
我发现我忽略了一点,就是不仅要检测行的重复,还要检测列的重复,如果照上面的时间复杂度,是只检测了行或列的重复,不可取。
既然这样,我们只能定义一个hash表,大小为n*n,来记录行和列的重复,时间复杂度不变。
可惜这种方法也不可取
class Solution { public: bool isValidSudoku(vector<vector<char>>& board) { int size = board[0].size(); vector<vector<int>> hash(size, vector<int>(size, 0)); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { if (board[i][j] == '.') continue; if (hash[i][board[i][j]-'0'] == 1) return false; hash[i][board[i][j] - '0'] = 1; if (hash[board[i][j] - '0'][j] == 1) return false; hash[board[i][j] - '0'][j] = 1; } } return true; } };如果按这样来,由于board[i]的范围在1-9,
hash[board[i][j] - '0'][j]是来判断行是否有重复,可是会覆盖列的hash表,造成误判。
只能用两个不同的hash来了,就不会出现覆盖。
<pre name="code" class="cpp">class Solution { public: bool isValidSudoku(vector<vector<char>>& board) { vector<vector<int>> hash1(10, vector<int>(10, 0)); vector<vector<int>> hash2(10, vector<int>(10, 0)); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (board[i][j] == '.') continue; if (hash1[i][board[i][j]-'0'] == 1) return false; hash1[i][board[i][j] - '0'] = 1; if (hash2[board[i][j] - '0'][j] == 1) return false; hash2[board[i][j] - '0'][j] = 1; } } return true; } };
可惜运行到这个地方出错,我觉得没问题啊,这个数独应该是合法的啊,还望哪个大神知道错在哪里,然后告知,感激不尽!
补充:原来我漏掉了一个判定条件,就是每个3*3子格的数字都要完全不同。下面补上正解:
class Solution { public: bool isValidSudoku(vector<vector<char> > &board) { int hash1[9][9] = { 0 }, hash2[9][9] = { 0 }, hash3[9][9] = { 0 }; for (int i = 0; i < board.size(); ++i) for (int j = 0; j < board[i].size(); ++j) if (board[i][j] != '.') { int num = board[i][j] - '0' - 1, k = i / 3 * 3 + j / 3; if (hash1[i][num] || hash2[j][num] || hash3[k][num]) return false; hash1[i][num] = hash2[j][num] = hash3[k][num] = 1; } return true; } };