题目
判断一个9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。
数字?1-9?在每一行只能出现一次。
数字?1-9?在每一列只能出现一次。
数字?1-9?在每一个以粗实线分隔的?3x3?宫内只能出现一次。
上图是一个部分填充的有效的数独。
数独部分空格内已填入了数字,空白格用?’.’?表示。
示例?1:
输入:
[
[“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”]
]
输出: true
示例2:
输入:
[
? [“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”]
]
输出: false
解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。
但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
说明:
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
给定数独序列只包含数字?1-9?和字符?’.’?。
给定数独永远是9x9形式的。
分析
1.其实思路很简单,根据题目要求我们可以发现其实是需要判断三个条件:
(1)判断每一行是否有重复字符
(2)判断每一列是够有重复字符
(3)判断每一个3*3九宫格是否存在重复
2.上面做法时间和内存消耗都会比较好,下面注释的做法时间会和上面这种差不多,但是内存消耗会比下面的
这种做法小一些。
3.checkout[3 * (i / 3) + j / 3][num]这个操作其实就是判断九宫格,但是虽然行是3,但是列是9
下面这种是最优解
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class MyClass
{
public:
bool isValidSudoku(vector<vector<char>>& board) {
if (board.empty()){
return false;
}
vector<vector<int>> checkout(9,vector<int>(9,0));
vector<vector<int>> row(9, vector<int>(9, 0));
vector<vector<int>> col(9, vector<int>(9, 0));
for (int i = 0; i < board.size(); ++i){
for (int j = 0; j < board[0].size(); ++j){
if (board[i][j] != '.'){
int num = board[i][j] - '0' - 1;
++row[i][num];
++col[j][num];
++checkout[3 * (i / 3) + j / 3][num];
if (row[i][num] == 2 || col[j][num] == 2 || checkout[3 * (i / 3) + j / 3][num] == 2){
return false;
}
}
}
}
return true;
}
};
下面这种方法比较好理解
bool isValidSudoku(vector<vector<char>>& board) {
int len=9;
//判断每一行是否满足
for(int i=0;i<len;++i)
{
if(isRowValid(i,board)==false)
return false;
}
//判断每一列是否满足
for(int i=0;i<len;++i)
{
if(isColumnValid(i,board)==false)
return false;
}
//判断每一个格子是否满足,每一次找到一个九宫格的左上角位置,以次为基准开始判断
for (int i = 0; i<len; i += 3)
{
for (int j = 0; j<len; j += 3)
{
if (isNineValid(i, j, board) == false)
return false;
}
}
return true;
}
bool isRowValid(int row, vector<vector<char>>& board)//判断单独一行是否有效
{
vector<char> temp;
for (int i = 0; i<board[0].size(); ++i)
{
if ('.' == board[row][i])
continue;
else
{
temp.push_back(board[row][i]);
}
//判断最后push进的元素是否与前面的相同,因为是先push,后比较,所以要小于size()-1
for (int j = 0; j<temp.size() - 1; ++j)
{
if (temp[j] == board[row][i])
return false;
}
}
return true;
}
bool isColumnValid(int column, vector<vector<char>>& board)//判断每一列是否有效
{
vector<char> temp;
for (int i = 0; i<board[0].size(); ++i)
{
if (board[i][column] == '.')
continue;
else
{
temp.push_back(board[i][column]);
}
//判断最后push进的元素是否与前面的相同,因为是先push,后比较,所以要小于size()-1
//之所以每次对比是因为这样可以发现重复及时退出,而且这样才能判断有无重复,否则全部压进去,
无法比较
for (int j = 0; j<temp.size() - 1; ++j)
{
if (temp[j] == board[i][column])
return false;
}
}
return true;
}
//判断单独一个九宫格是否有效
bool isNineValid(int row, int column, vector<vector<char>>& board)
{
vector<char> temp;
for (int i = row; i < row + 3; ++i)
{
for (int j = column; j < column + 3; ++j)
{
if (board[i][j] == '.')
continue;
else
{
temp.push_back(board[i][j]);
}
for (int k = 0; k < temp.size() - 1; ++k)
{
if (temp[k] == board[i][j])
return false;
}
}
}
return true;
}