http://www.lintcode.com/en/problem/valid-sudoku/
注意点: 整块中按列选取子块,子块里按列遍历,对应的角标应该如何设置,考虑清楚。
i = 0- 9, i /3 = 0,0,0,1,1,1......
i%3 = 0,1,2,0,1,2.......
[k/3,k%3] 表示子块按列填充;[j,i]表示在整块中子块是按行选取的!
set的巧妙使用,保证不重复
1 public boolean isValidSudoku(char[][] board) { 2 boolean[] test = new boolean[9]; 3 for(int i = 0; i < 9; i++) { //列遍历 4 Arrays.fill(test, false); 5 for(int j = 0; j < 9; j++) { 6 if(!visited(test, board[j][i])) return false; 7 } 8 } 9 for(int i = 0; i < 9; i++) { //行遍历 10 Arrays.fill(test, false); 11 for(int j = 0; j < 9; j++) { 12 if(!visited(test, board[i][j])) return false; 13 } 14 } 15 for(int i = 0; i < 9; i += 3){ 16 for(int j = 0; j < 9; j += 3) { 17 Arrays.fill(test, false); 18 for(int k = 0; k < 9; k++) { //[k/3,k%3] 表示子块按列填充;[j,i]表示在整块中子块是按列选取的, 19 //一列中选完子块再从第二列开始选子块 20 if(!visited(test,board[j+ k / 3][i + k % 3])) return false; 21 } 22 } 23 } 24 return true; 25 /*1 4 7 26 2 5 8 27 3 6 9 */ 28 } 29 //visited,表示是否访问过,一旦被调用,return true 表示访问过且符合要求,false表示不符合要求,不是数独。 30 private boolean visited(boolean[] process, char ch) { 31 if(ch == '.') return true; 32 int m = ch - '0'; 33 if(process[m - 1] || m > 9 || m < 1) return false; //如果第m-1个位置已经被放过元素,说明有重复元素加进来,return false 34 process[m - 1] = true; // 数字 8就放在数组的第八个位置。 35 return true; 36 }
1 public boolean isValidSudoku(char[][] board) { 2 Set<String> set = new HashSet<String>(); 3 for(int i = 0; i < 9 ; i++) { 4 for(int j = 0; j < 9; j++) { 5 char ch = board[i][j]; 6 //每从矩阵中取一个char,都要在set中放三次,分别是char在第几行,第几列,第几子块 7 //如果一个字符不能放三次,set由于要保证数据不重复,所以说明之前肯定放过,也即字符发生了重复。 8 if(ch != '.') { 9 if(!set.add(ch + "in row" + i) || !set.add(ch + "in col" + j) || !set.add(ch + "in block" + i/3 +'-' + j/3)) { 10 return false; 11 } 12 } 13 } 14 } 15 return true; 16 }