LeetCode - 36. Valid Sudoku

这道题就是根据已给出的数组中的数来判断该数组是不是Valid的,也就是行,列,九宫格中都不能出现相同的数字。


A partially filled sudoku which is valid. 上边的这个数组就是valid的。

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

用 '.' 表示空的位置,空的位置跳过就好了。

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

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. 一列里边有两个8,第一个九宫格里边也有两个8,就不是valid。

解:

    这道题比较简单,因为只需要判断从给出的数字中有没有出现行,列,或者九宫格中重复的数字即可,这个数组有没有解这道题并不关心。

    很直接的想法就是分别看每行,每列,每个九宫格中有没有出现过重复的数字。用unordered_set很容易实现。

bool isValidSudoku(vector<vector<char>>& board)
{
    unordered_set<char> setB;
    // 判断行
    for(int i = 0; i < 9; i++){
        setB.clear();
        for(int j = 0; j < 9; j++){
            if(board[i][j] != '.')
            {
                if(setB.find(board[i][j]) != setB.end())
                    return false;
                else
                    setB.insert(board[i][j]);
            }
        }
    } 
    
    // 判断列
    for(int i = 0; i < 9; i++){
        setB.clear();
        for(int j = 0; j < 9; j++){
            if(board[j][i] != '.')
            {
                if(setB.find(board[j][i]) != setB.end())
                    return false;
                else
                    setB.insert(board[j][i]);
            }
        }
    }
    
    // 判断九宫格
    for(int i = 0; i < 9; i += 3){
        for(int j = 0; j < 9; j += 3){
            setB.clear();
            for(int x = 0; x < 3; x++){
                for(int y = 0; y < 3; y++){
                    if(board[i + x][j + y] != '.')
                    {
                        if(setB.find(board[i + x][j + y]) != setB.end())
                            return false;
                        else
                            setB.insert(board[i + x][j + y]);
                    }
                }
            }
        }
    }
    return true;
}

    所有的算法都应该是这种思想,判断三种情况下有没有重复的,有的话直接返回false,全判断玩还没有错就返回true。但是有更简便的写法,就是用三个9 * 9数组表示行,列,九宫格中的数字有没有出现过,比如row_appear[1][2] = 1,就表示,第1行中,2出现过了,如果等于0就是没出现过。所以在初始化时需要将三个数组全初始化为0,表示遍历board数组之前,所有数都没有出现过。代码如下:

bool isValidSudoku(vector<vector<char> > &board)
{
    // 因为要初始化为0,所以直接就这么写了,否则不行
    int row_appear[9][9] = {0}, col_appear[9][9] = {0}, box_appear[9][9] = {0};
        
    for(int i = 0; i < board.size(); ++ i)
        for(int j = 0; j < board[i].size(); ++ j)
            if(board[i][j] != '.')
            {
                int num = board[i][j] - '0' - 1;    // 因为行,列,九宫格的数都是 0 ~ 8
                int k = i / 3 * 3 + j / 3;          // 第几个九宫格
                if(row_appear[i][num] || col_appear[j][num] || box_appear[k][num])
                    return false;
                row_appear[i][num] = col_appear[j][num] = box_appear[k][num] = 1;
            }
    return true;
}

    每个数组中的数只有1和0两种可能,a[i][j] = 1(泛指三个数组) 表示这个数组中第 i 行出现过 j 这个数了:

    1、如果是表示行的数组,则表示board数组中,第 i 行出现过了 j 这个数;

    2、如果是表示列的数组,则表示board数组中,第 i 列出现过了 j 这个数;

    3、如果是表示九宫格的数组,则表示board数组中,第 i 个九宫格中出现过了 j 这个数。

    九宫格的顺序按照代码中的写法应该是下图。

猜你喜欢

转载自blog.csdn.net/Bob__yuan/article/details/82353583