看到解数独就想到了N皇后问题,关键点是如何将题目中的合法条件转换为代码
题目: 36. 有效的数独链接
思路
首先我先考虑的是如何,如何满足题目中的三个条件。刚开始想到用unordered_map<int,set> 后来发现其实可以用数组来存;
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
1.“行”:重复判断:raw[0]代表第0行的一类的数 raw[0][1] 代表着第0行值为1的数是否已经存在
vector<vector<bool>> raw(9,vector<bool> (10,false));
2.同理“列”重复判断
vector<vector<bool>> batch(9,vector<bool>(10,false));
3."块”重复判断:这个比较难理解了。就是每batch【0】(对应的是9题目中的九个块中的一个块),batch【0】【1】代表着第0块值为1的数是否已经存在
vector<vector<bool>> batch(9,vector<bool>(10,false));
代码:
class Solution {
private:
public:
bool isValidSudoku(vector<vector<char>>& board) {
vector<vector<bool>> raw(9,vector<bool> (10,false));//raw[0]代表第0行的一类的数 raw[0][1] 代表着第0行值为1的数是否已经存在
vector<vector<bool>> col(9,vector<bool> (10,false));//同理
vector<vector<bool>> batch(9,vector<bool>(10,false));//这个比较难理解了。就是每batch【0】(对应的是9题目中的九个块中的一个块),batch【0】【1】代表着第0块值为1的数是否已经存在
//上面其实每个元素的集合可以存十个数,但是原题目的数字是1-9,是为了使得数字比较好计算,1放在某个数组中1号位置,2放在某个数组中的2好位置
for(int i=0;i<board.size();i++)
for(int j=0;j<board[0].size();j++)
{
if(board[i][j]=='.') continue;
int value=board[i][j]-'0';
int bactch_value=(i/3)*3 +j/3;
if(raw[i][value]==true||col[j][value]==true||batch[bactch_value][value]==true) return false;
else
{
raw[i][value]=true;
col[j][value]=true;
batch[bactch_value][value]=true;
}
}
return true;
}
};
题目:37. 解数独 链接
思路:
代码:
class Solution {
private:
//vector<vector<bool>> used(9, vector<bool>(9, false));
vector<vector<bool> > row ;//
vector<vector<bool> > col ;//
vector<vector<bool> > batch;
bool isLegal(vector<vector<char>>&board, int current_i, int current_j)
{
int value = board[current_i][current_j] - '0';
int batch_index = (current_i / 3) * 3 + current_j / 3;
if (row[current_i][value] == true || col[current_j][value] == true || batch[batch_index][value] == true) return false;//都已经存在
return true;
}
bool dfs(vector<vector<char>>&board, vector<vector<bool>>&used, int start_i, int start_j)
{
//cout<<"start_i="<<start_i<<" start_j="<<start_j<<" board[start_i][start_j]="<<board[start_i][start_j]<<" used[start_i][start_j]="<<used[start_i][start_j]<<endl;
if (start_j == board[0].size())
{
//cout<<"开始了下一行判断"<<endl;
//cout<<"zjs"<<endl;
start_i = start_i + 1;
start_j = 0;
}
if (start_i >= board.size())
{
cout<<"找到哦了"<<endl;
//cout<<board[0][2]<<" "<<board[0][3]<<" "<<board[0][3]<<endl;
return true;//这个代表着行到达了最后也就是全部数字填完了
}
if(used[start_i][start_j] == false)
{
for (int i = 1;i <= 9;i++)//也就是每个位置都可以是1 -9之间的数字
{
//cout<<"1"<<endl;
board[start_i][start_j] = i + '0';
//cout<<"currentV="<<board[start_i][start_j]<<endl;
if ( isLegal(board, start_i, start_j))
{
//cout<<"2"<<endl;
int value = i;
int batch_index = (start_i / 3) * 3 + start_j / 3;
// cout<<"数字填充start_i="<<start_i<<" start_j="<<start_j<<" board[start_i][start_j]="<<board[start_i][start_j]<<endl;
//cout<<"数字填充row[start_i][value]="<<row[start_i][value]<<" col[start_j][value]="<<col[start_j][value]<<" batch[batch_index][value]="<<batch[batch_index][value]<<endl;
//used[start_i][start_j]==false 这个代表着某些题目已知的数字不能动
row[start_i][value] = true;//
col[start_j][value] = true;
batch[batch_index][value] = true;
if (dfs(board, used, start_i, start_j+1)) return true;//找到了才返回,不然接着继续找
row[start_i][value]=false;
col[start_j][value] = false;
batch[batch_index][value] = false;
}
}
}else
{
//cout<<"3"<<endl;
if (dfs(board, used, start_i, start_j+1)) return true;
//return dfs(board, used, start_i, start_j+1);
}
return false;
}
public:
void solveSudoku(vector<vector<char>>& board)
{
row= vector<vector<bool> > (9, vector<bool>(10, false));
col = vector<vector<bool> >(9, vector<bool>(10, false));
batch = vector<vector<bool> >(9, vector<bool>(10, false));
vector<vector<bool>> used(9, vector<bool>(9, false));
for (int i = 0;i < board.size();i++)
{
for (int j = 0;j < board[0].size();j++)
{
if (board[i][j] == '.') continue;
int value = board[i][j] - '0';//取值范围时【1,9】之间
//cout<<"value="<<value<<endl;
row[i][value] = true;//
col[j][value] = true;
int batch_index = (i / 3) * 3 + j / 3;
batch[batch_index][value] = true;
used[i][j] = true;
}
}
int start_i = 0;
int start_j = 0;
dfs(board, used, start_i, start_j);
}
};