题目:
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.
链接: http://leetcode.com/problems/valid-sudoku/
4/4/2017
33%,39ms
做过的,又全部忘记了,尤其是block那个部分
http://www.cnblogs.com/panini/p/5574949.html
1 public class Solution { 2 public boolean isValidSudoku(char[][] board) { 3 if (board.length != 9 || board[0].length != 9) return false; 4 5 Set<Character> rows = new HashSet<Character>(); 6 Set<Character> columns = new HashSet<Character>(); 7 Set<Character> blocks = new HashSet<Character>(); 8 9 for (int i = 0; i < 9; i++) { 10 for (int j = 0; j < 9; j++) { 11 if (board[i][j] != '.' && !rows.add(board[i][j])) return false; 12 if (board[j][i] != '.' && !columns.add(board[j][i])) return false; 13 int row = i / 3 * 3; 14 int column = i % 3 * 3; 15 if (board[row + j / 3][column + j % 3] != '.' && !blocks.add(board[row + j / 3][column + j % 3])) return false; 16 } 17 rows.clear(); 18 columns.clear(); 19 blocks.clear(); 20 } 21 return true; 22 } 23 }
解释block可以看讨论:
Great solution!. Just trying to explain how to think about
%
and/
. These two operators can be helpful for matrix traversal problems.For a block traversal, it goes the following way.
0,0
,0,1
,0,2
; < --- 3 Horizontal Steps followed by 1 Vertical step to next level.
1,0
,1,1
,1,2
; < --- 3 Horizontal Steps followed by 1 Vertical step to next level.
2,0
,2,1
,2,2
; < --- 3 Horizontal Steps.And so on...
But, thej
iterates from0 to 9
.But we need to stop after 3 horizontal steps, and go down 1 step vertical.
Use
%
for horizontal traversal. Because%
increments by 1 for each j :0%3 = 0 , 1%3 = 1, 2%3 = 2
, and resets back. So this covers horizontal traversal for each block by 3 steps.Use
/
for vertical traversal. Because/
increments by 1 after every 3 j:0/3 = 0; 1/3 = 0; 2/3 =0; 3/3 = 1
.So far, for a given block, you can traverse the whole block using just j.
But because j is just 0 to 9, it will stay only first block. But to increment block, use i. To move horizontally to next block, use
%
again :ColIndex = 3 * i%3
(Multiply by 3 so that the next block is after 3 columns. Ie0,0
is start of first block, second block is0,3
(not0,1
);Similarly, to move to next block vertically, use
/
and multiply by 3 as explained above. Hope this helps.
https://discuss.leetcode.com/topic/9748/shared-my-concise-java-code
别人的讨论:
https://discuss.leetcode.com/topic/27436/short-simple-java-using-strings
奇葩的使用string set,不能更直观了
1 public boolean isValidSudoku(char[][] board) { 2 Set seen = new HashSet(); 3 for (int i=0; i<9; ++i) { 4 for (int j=0; j<9; ++j) { 5 char number = board[i][j]; 6 if (number != '.') 7 if (!seen.add(number + " in row " + i) || 8 !seen.add(number + " in column " + j) || 9 !seen.add(number + " in block " + i/3 + "-" + j/3)) 10 return false; 11 } 12 } 13 return true; 14 }
另外一个,直接用数组存放,很好的算法
https://discuss.leetcode.com/topic/40078/yet-another-java-2ms-solution
1 public boolean isValidSudoku(char[][] board) { 2 int [] vset = new int [9]; 3 int [] hset = new int [9]; 4 int [] bckt = new int [9]; 5 int idx = 0; 6 for (int i = 0; i < 9; i++) { 7 for (int j = 0; j < 9; j++) { 8 if (board[i][j] != '.') { 9 idx = 1 << (board[i][j] - '0') ; 10 if ((hset[i] & idx) > 0 || 11 (vset[j] & idx) > 0 || 12 (bckt[(i / 3) * 3 + j / 3] & idx) > 0) return false; 13 hset[i] |= idx; 14 vset[j] |= idx; 15 bckt[(i / 3) * 3 + j / 3] |= idx; 16 } 17 } 18 } 19 return true; 20 }
更多讨论: