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.
https://leetcode.com/problems/valid-sudoku/
就是看看每行是否有重复的数字,然后看看每列,最后看小方块。
正好用了一下最近get的新姿势,没有用map存1-9是否访问过。
一个变量_bit就记下了这新信息,用位运算。
比如来的数是4,就是100,与_bit做位与,如果没有出现过100&000是0,否则100&100不等于0,最后用100|000记下4已经访问过了。
人参第一次使用四重循环,这种酸爽不敢相信。我用脚趾猜row,column,square这3种情况可以合并,但是为了纪念我人生的第一次四重循环,就这样吧(其实是懒。
不行,不重构一下我睡不着,后面有简化版。
1 /** 2 * @param {character[][]} board 3 * @return {boolean} 4 */ 5 var isValidSudoku = function(board) { 6 this._bit = 0; 7 function isValid(num){ 8 var tmp = Math.pow(2, num - 1); 9 if((this._bit & tmp) !== 0){ 10 return false; 11 }else{ 12 this._bit = this._bit | tmp; 13 return true; 14 } 15 } 16 17 var i = 0, j = 0, m = 0, n =0, cell = 0; 18 //row 19 for(i = 0; i < 9; i++){ 20 for(j = 0; j < 9; j++){ 21 cell = parseInt(board[i][j]); 22 if(!isValid(cell)){ 23 return false; 24 } 25 } 26 this._bit = 0; 27 } 28 //column 29 for(i = 0; i < 9; i++){ 30 for(j = 0; j < 9; j++){ 31 cell = parseInt(board[j][i]); 32 if(!isValid(cell)){ 33 return false; 34 } 35 } 36 this._bit = 0; 37 } 38 //square 39 for(i = 0; i <= 6; i+=3){ 40 for(j = 0; j <=6 ; j+=3){ 41 for(m = 0; m < 3; m++){ 42 for(n = 0; n < 3; n++){ 43 cell = parseInt(board[m + i][n + j]); 44 if(!isValid(cell)){ 45 return false; 46 } 47 } 48 } 49 this._bit = 0; 50 } 51 } 52 return true; 53 };
合并3种情况比较麻烦啊...
前面2种好说,square的循环很纠结。
首先要用内层循环j的0-8算出下面的下标:
(0,0) (0,1) (0,2)
(1,0) (1,1) (2,2)
(2,0) (2,1) (2,2)
规律就是X = j / 3, Y = j % 3
然后要用外层循环i的0-8遍历第0个到第8个square
(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)
(1,0) (1,1) (2,2) (1,3) (1,4) (2,5)
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)
(3,0) (3,1) (3,2)
(4,0) (4,1) (4,2)
(5,0) (5,1) (5,2)
画三个就能看出规律了吧,右边的square跟左上的square相比Y多了3; 下边的square跟左上的square相比X多了3;
在内层循环的square之上加上的偏移量是:
(0,0) (0,3) (0,6)
(3,0) (3,3) (3,6)
(6,0) (6,3) (6,6)
规律就是X = (i / 3) * 3, Y = (i % 3) * 3
所以合起来就是X = (i / 3) * 3 + (j / 3) , Y = (i % 3) * 3 + (j % 3)
好费劲,心好累。
简化版在此!
js对象是引用传递,在方法里改这对象的val,相当于C指针的变通。
1 /** 2 * @param {character[][]} board 3 * @return {boolean} 4 */ 5 var isValidSudoku = function(board) { 6 function isValid(num, flag){ 7 var tmp = Math.pow(2, num - 1); 8 if((flag.val & tmp) !== 0){ 9 return false; 10 }else{ 11 flag.val = flag.val | tmp; 12 return true; 13 } 14 } 15 16 var i = 0, j = 0, m = 0, n =0, cell = 0; 17 var row = {val : 0}, column = {val : 0}, square = {val : 0}; 18 for(i = 0; i < 9; i++){ 19 for(j = 0; j < 9; j++){ 20 cell = parseInt(board[i][j]); 21 if(!isValid(cell, row)){ 22 return false; 23 } 24 cell = parseInt(board[j][i]); 25 if(!isValid(cell, column)){ 26 return false; 27 } 28 cell = parseInt(board[parseInt(i / 3) * 3 + parseInt(j / 3)][(i % 3) * 3 + (j % 3)]); 29 if(!isValid(cell, square)){ 30 return false; 31 } 32 } 33 row.val = column.val = square.val = 0; 34 } 35 return true; 36 };