36. Valid Sudoku

题目:

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,00,10,2; < --- 3 Horizontal Steps followed by 1 Vertical step to next level.

1,01,11,2; < --- 3 Horizontal Steps followed by 1 Vertical step to next level.

2,02,12,2; < --- 3 Horizontal Steps.

And so on...
But, the j iterates from 0 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. Ie 0,0 is start of first block, second block is 0,3 (not 0,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 }

更多讨论:

https://discuss.leetcode.com/category/44/valid-sudoku

原文地址:https://www.cnblogs.com/panini/p/6712953.html