【Valid Sudoku】cpp

题目

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.

代码

class Solution {
public:
bool isValidSudoku(std::vector<std::vector<char> > &board)
        {
            int len = board.size();
            if (len != 9) return false;
            bool row_check[9];
            bool col_check[9];
            bool subBox_check[9];
            for (int row = 0; row < len; ++row)
            {
                std::fill(row_check, row_check+9, false);
                std::fill(col_check, col_check+9, false);
                std::fill(subBox_check, subBox_check+9, false);
                for (int col = 0; col < len; ++col)
                {
                    if (!Solution::if_valid(board, row, col, row_check)){
                        return false;
                    }
                    if (!Solution::if_valid(board, col, row, col_check)){
                        return false;
                    }
                    if (!Solution::if_valid(board, 3*(row/3)+col/3, 3*(row%3)+col%3, subBox_check)){
                        return false;
                    }
                }
            }
            return true;
        }
static bool if_valid(std::vector<std::vector<char> > &board, int x, int y, bool (&some_check)[9])
        {
            if (board[x][y]=='.'){
                return true;
            }
            else{
                if (some_check[board[x][y]-'1']){
                    return false;
                }
                else{
                    some_check[board[x][y]-'1'] = true;
                    return true;
                }
            }
            return false;
        }
};

Tips

1. 整体逻辑按照数独的要求走:

  a. 判断同一行

  b. 判断同一列

  c. 判断所在的sub box

2. 判断时主要利用的数据结构是类似HashSet,由于三类判断条件类似,因此单独提出来一段代码。

3. 一点儿技巧:这里时间复杂度没有什么可说的就是O(n²);可以做些文章的地方就是代码复杂度,如何遍历一次for..for...就判断完成全部的逻辑。

  a. 这里的核心就在于数独是对称的矩阵,行列对称;因此,行列坐标互换就可以走一次for...for...就完成1.a和1.b的判断逻辑。

  b. 这里还需要注意的是,for..for..中走完一列,则需要判断一个sub box是否valid;因此,需要将某一列的坐标映射到某个sub box上。搞清楚这一点就可以推理处坐标变换的公式。

4. 在离线测试的时候,处理c++的 vector 二维字符数组还是非常不熟练,由Python转成cpp刷题确实不太习惯。后面在刷到string的题目时候,再把这cpp这部分强化一下。

==================================================

第二次过这道题,第一次没有AC还是错在了sub matrix小方块的检验上面。

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
            for ( int i=0; i<board.size(); ++i )
            {
                // check row
                vector<bool> row_used(9,false);
                for ( int j=0; j<board[i].size(); ++j )
                {
                    if ( board[i][j]!='.' )
                    {
                        if ( row_used[board[i][j]-'1'] ) return false;
                        row_used[board[i][j]-'1'] = true;
                    }
                }
                // check col
                vector<bool> col_used(9,false);
                for ( int j=0; j<board.size(); ++j)
                {
                    if ( board[j][i]!='.')
                    {
                        if ( col_used[board[j][i]-'1'] ) return false;
                        col_used[board[j][i]-'1'] = true;
                    }
                }
                // check sub matrix
                vector<bool> subm_used(9,false);
                for ( int j=0; j<board[i].size(); ++j )
                {
                    int row = 3*(i/3) + j/3;
                    int col = 3*(i%3) + j%3;
                    if ( board[row][col]!='.' )
                    {
                        if ( subm_used[board[row][col]-'1'] ) return false;
                        subm_used[board[row][col]-'1'] = true;
                    }
                }
            }
            return true;
    }
};

tips:

这个要记住了
row = 3*(i/3) + j/3

col = 3*(i%3) + j%3

原文地址:https://www.cnblogs.com/xbf9xbf/p/4456871.html