[LeetCode] 36. Valid Sudoku 验证数独

Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:

  1. Each row must contain the digits 1-9 without repetition.
  2. Each column must contain the digits 1-9 without repetition.
  3. Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.


A partially filled sudoku which is valid.

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.

Example 1:

Input:
[
  ["5","3",".",".","7",".",".",".","."],
  ["6",".",".","1","9","5",".",".","."],
  [".","9","8",".",".",".",".","6","."],
  ["8",".",".",".","6",".",".",".","3"],
  ["4",".",".","8",".","3",".",".","1"],
  ["7",".",".",".","2",".",".",".","6"],
  [".","6",".",".",".",".","2","8","."],
  [".",".",".","4","1","9",".",".","5"],
  [".",".",".",".","8",".",".","7","9"]
]
Output: true

Example 2:

Input:
[
  ["8","3",".",".","7",".",".",".","."],
  ["6",".",".","1","9","5",".",".","."],
  [".","9","8",".",".",".",".","6","."],
  ["8",".",".",".","6",".",".",".","3"],
  ["4",".",".","8",".","3",".",".","1"],
  ["7",".",".",".","2",".",".",".","6"],
  [".","6",".",".",".",".","2","8","."],
  [".",".",".","4","1","9",".",".","5"],
  [".",".",".",".","8",".",".","7","9"]
]
Output: false
Explanation: Same as Example 1, except with the 5 in the top left corner being 
    modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.

Note:

  • A Sudoku board (partially filled) could be valid but is not necessarily solvable.
  • Only the filled cells need to be validated according to the mentioned rules.
  • The given board contain only digits 1-9 and the character '.'.
  • The given board size is always 9x9.

数独 是一种逻辑性的数字填充游戏,玩家须以数字填进每一格,而每行、每列和每个宫(即3x3的大格)有齐1至9所有数字。游戏设计者会提供一部分的数字,使谜题只有一个答案。

题目要求验证一个方阵是否为数独,判断标准是看各行各列是否有重复数字,以及每个小的3x3的小方阵里面是否有重复数字,如果都无重复,则当前矩阵是数独。但不代表该数独有解,只是判断当前未填完的矩阵是否是数独。

解法:遍历方阵中的每个数字,检查包含当前位置的行和列以及3x3小方阵中是否已经出现该数字,需要分别记录行,列,小方阵是否出现该数字。

Java:

public class Solution {
    static int position[]=new int[]{2,4,8,16,32,64,128,256,512};
    /**
     * 分别判断行 列 和 格子内的就可以了~~~
     * 这里我使用的位运算来降低内存。。都是2的n次,那么对应的位置上直接使用位运算就能判断了
     * */
    public boolean isValidSudoku(char[][] board) {
        int col[]=new int[9];
        int row[]=new int[9];
        int zone[]=new int[9];
        int i,j,mask,qid;
        for(i=0;i<9;i++){
            for(j=0;j<9;j++){
                if(board[i][j]=='.')
                    continue;
                mask=position[board[i][j]-'1'];
                qid=(i/3)*3+j/3;
                if( (col[j] | mask) == col[j] || (row[i] | mask) == row[i] ||(zone[qid] | mask) == zone[qid])
                    return false;
                col[j]=col[j]|mask;
                row[i]=row[i]|mask;
                zone[qid]=zone[qid]|mask;
            }
        }
        return true;

    }
}  

Java:

public class Solution {  
    //置为静态变量  
    static Map<Character,Integer> map = new HashMap<Character,Integer>();  
    public boolean isValidSudoku(char[][] board) {  
        //判断每行  
        for(int i = 0; i < board.length; i++){  
            initMap();//每次均需初始化  
            for(int j = 0; j < board[0].length; j++){  
                //是数字  
                if(board[i][j] >= '0' && board[i][j] <= '9'){  
                    if(map.get(board[i][j]) > 0){//说明重复数字  
                        return false;  
                    }else{  
                        map.put(board[i][j],1);  
                    }  
                }else if(board[i][j] != '.'){//出现空格和0-9之外的字符  
                    return false;//直接返回false  
                }  
            }  
        }  
        //判断每列  
        for(int i = 0; i < board[0].length; i++){  
            initMap();//每次均需初始化  
            for(int j = 0; j < board.length; j++){  
                //是数字  
                if(board[j][i] >= '0' && board[j][i] <= '9'){  
                    if(map.get(board[j][i]) > 0){//说明重复数字  
                        return false;  
                    }else{  
                        map.put(board[j][i],1);  
                    }  
                }else if(board[j][i] != '.'){//出现空格和0-9之外的字符  
                    return false;//直接返回false  
                }  
            }  
        }  
        //判断九宫格  
        for(int i = 0; i < board.length - 2; i = i+3){//行{  
            for(int j = 0; j < board[0].length - 2; j=j+3){  
                initMap();//初始化  
                for(int m = i; m < i + 3;m++){  
                    for(int n = j; n < j+3; n++){  
                        //是数字  
                        if(board[m][n] >= '0' && board[m][n] <= '9'){  
                            if(map.get(board[m][n]) > 0){//说明重复数字  
                                return false;  
                            }else{  
                                map.put(board[m][n],1);  
                            }  
                        }else if(board[m][n] != '.'){//出现空格和0-9之外的字符  
                            return false;//直接返回false  
                        }  
                    }  
                }  
            }  
        }  
        return true;  
    }  
    //初始化map为每个key均赋值0  
    private void initMap(){  
        for(char i = '0';i <= '9'; i++){  
            map.put(i,0);  
        }  
    }  
}  

Python:

class Solution(object):
    def isValidSudoku(self, board):
        """
        :type board: List[List[str]]
        :rtype: bool
        """
        for i in xrange(9):
            if not self.isValidList([board[i][j] for j in xrange(9)]) or \
               not self.isValidList([board[j][i] for j in xrange(9)]):
                return False
        for i in xrange(3):
            for j in xrange(3):
                if not self.isValidList([board[m][n] for n in xrange(3 * j, 3 * j + 3) \
                                                     for m in xrange(3 * i, 3 * i + 3)]):
                    return False
        return True
    
    def isValidList(self, xs):
        xs = filter(lambda x: x != '.', xs)
        return len(set(xs)) == len(xs)

C++:

class Solution {
public:
    bool isValidSudoku(vector<vector<char> > &board) {
        if (board.empty() || board[0].empty()) return false;
        int m = board.size(), n = board[0].size();
        vector<vector<bool> > rowFlag(m, vector<bool>(n, false));
        vector<vector<bool> > colFlag(m, vector<bool>(n, false));
        vector<vector<bool> > cellFlag(m, vector<bool>(n, false));
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (board[i][j] >= '1' && board[i][j] <= '9') {
                    int c = board[i][j] - '1';
                    if (rowFlag[i][c] || colFlag[c][j] || cellFlag[3 * (i / 3) + j / 3][c]) return false;
                    rowFlag[i][c] = true;
                    colFlag[c][j] = true;
                    cellFlag[3 * (i / 3) + j / 3][c] = true;
                }
            }
        }
        return true;
    }
};

 

All LeetCode Questions List 题目汇总

  

 

posted @ 2018-03-13 14:22  轻风舞动  阅读(801)  评论(0编辑  收藏  举报