题目:
解答:
是很久以前做的了,代码有点长。。有空要去重新改造下。
简单的思路是这样的:
- 建立一个9*9的数独可选数集,每个集合包含1-9九个数
- 根据已有数独数据,如果是确定的数据,将集合数修改为只包含一个数
- 根据数独的已有数,对行、列、中等格的9个数进行筛选,每个单元的集合数筛除该单元不可存在的数。
- 如果筛选后结果只有一个可能,那这个位置的数也确定了。
- 如果经过筛选后,没有新增确定数,那么,将当前数独可选集压入栈中,然后按序选出第一个不确定数,将其设定为第一个。继续上面步骤,如果此时,发现有冲突了,则退回栈中可选数集,改为第二个,如果继续遇到没有新增确定数,那么将此时的可选数集压入栈中,按序选出下一个不确定数。
- 可选数集内所有数均只有一个的时候,数独填充完毕。
代码:
class Solution {
public:
struct ShuDuIndex
{
int i;
int j;
int index;
};
void initHelpData(vector<vector<list<int>>>& t)
{
t.clear();
list<int> tmp;
for(int i = 1;i <= 9;++i)
tmp.push_back(i);
for(int i = 0;i < 9; ++i)
{
vector<list<int>> listtmp;
for(int j = 0;j < 9;++j)
{
listtmp.push_back(tmp);
}
t.push_back(listtmp);
}
}
bool HasFinished(vector<vector<int>>& t)
{
for(int i = 0;i < 9;++i)
for(int j = 0;j < 9; ++j)
if(t[i][j] == 0)
return false;
return true;
}
void updateHelpData(vector<vector<int>>& t, vector<vector<list<int>>>& helper)
{
for(int i = 0;i < 9; ++i)
for(int j = 0;j < 9; ++j){
if(t[i][j] != 0){
helper[i][j].clear();
helper[i][j].push_back(t[i][j]);
}
}
}
int freshHelperData(vector<vector<int>>& shudu, vector<vector<list<int>>>& t, int indexx, int indexy)
{
int num = shudu[indexx][indexy];
for(int index = 0;index < 9; ++index){
if(shudu[indexx][index] == 0 ){
list<int>::iterator it = find(t[indexx][index].begin(),
t[indexx][index].end(), num);
if(it != t[indexx][index].end()){
t[indexx][index].erase(it);
if(t[indexx][index].empty()) {
//cout << "line4 empty " << indexx << " " << index << endl;
return -1;
}
}
}
if(shudu[index][indexy] == 0){
list<int>::iterator it = find(t[index][indexy].begin(), t[index][indexy].end(), num);
if(it != t[index][indexy].end()){
t[index][indexy].erase(it);
if(t[index][indexy].empty()) {
//cout << "line5 empty " << index << " " << indexy << endl;
return -1;
}
}
}
}
for(int m = indexx - indexx % 3;m < indexx - indexx % 3 + 3; ++m)
for(int n = indexy - indexy % 3;n < indexy - indexy % 3 + 3; ++n){
if(shudu[m][n] == 0){
list<int>::iterator it = find(t[m][n].begin(), t[m][n].end(), num);
if(it != t[m][n].end()){
t[m][n].erase(it);
if(t[m][n].empty()) {
//cout << "line6 empty " << m << " " << n << endl;
return -1;
}
}
}
}
return 0;
}
int changeShuDu(vector<vector<int>>& shudu, vector<vector<list<int>>>& t)
{
bool hasChanged = false;
for(int i = 0;i < 9; ++i)
for(int j = 0;j < 9;++j){
if(shudu[i][j] != 0){
for(int k = 0;k < 9; ++k){
if(k != i){
list<int>::iterator it = find(t[k][j].begin(), t[k][j].end(), shudu[i][j]);
if(it != t[k][j].end()){
t[k][j].erase(it);
if(t[k][j].empty()) {
//cout << "list1 empty " << k << " " << j << endl;
return -1;
}
}
}
}
for(int k = 0;k < 9; ++k){
if(k != j){
list<int>::iterator it = find(t[i][k].begin(), t[i][k].end(), shudu[i][j]);
if(it != t[i][k].end()){
t[i][k].erase(it);
if(t[i][k].empty()) {
//cout << "line2 empty " << i << " " << k << endl;
return -1;
}
}
}
}
int indexx = i - i % 3;
int indexy = j - j % 3;
for(int k = indexx;k < indexx + 3;++k)
for(int d = indexy;d < indexy + 3;++d){
if(!(k == i && d == j)){
list<int>::iterator it = find(t[k][d].begin(), t[k][d].end(), shudu[i][j]);
if(it!=t[k][d].end()){
t[k][d].erase(it);
if(t[k][d].empty()) {
//cout << "line3 empty " << k << " " << d << endl;
return -1;
}
}
}
}
}//end if(shudu[i][j] != 0)
}// for(int j = 0;j < 9;++j)
for(int i = 0;i < 9; ++i)
for(int j = 0;j < 9; ++j)
if(shudu[i][j] == 0 && t[i][j].size() == 1){
//cout << "i,j " << i << " " << j << endl;
shudu[i][j] = *(t[i][j].begin());
if(freshHelperData(shudu, t, i, j)<0) return -1;
hasChanged = true;
}
for(int i = 0;i < 9; ++i){ //横着的,用排除法
for(int num = 1;num <= 9; ++num){
int index = -1, numcnt = 0;
bool stop = false;
for(int j = 0;j < 9; ++j){
if(shudu[i][j] == num){
stop = true;
break;
}
list<int>::iterator it = find(t[i][j].begin(), t[i][j].end(), num);
if(it != t[i][j].end()){
index = j;
numcnt++;
}
}
if(stop) continue;
if(numcnt == 1){
t[i][index].clear();
t[i][index].push_back(num);
shudu[i][index] = num;
if(freshHelperData(shudu, t, i, index)<0) return -1;
hasChanged = true;
}
}
}
for(int i = 0;i < 9; ++i){ //竖着的,用排除法
for(int num = 1;num <= 9; ++num){
int index = -1, numcnt = 0;
bool stop = false;
for(int j = 0;j < 9; ++j){
if(shudu[j][i] == num){
stop = true;
break;
}
list<int>::iterator it = find(t[j][i].begin(), t[j][i].end(), num);
if(it != t[j][i].end()){
index = j;
numcnt++;
}
}
if(stop) continue;
if(numcnt == 1){
t[index][i].clear();
t[index][i].push_back(num);
shudu[index][i] = num;
if(freshHelperData(shudu, t, index, i)<0) return -1;
hasChanged = true;
}
}
}
for(int i = 0;i < 9;i = i + 3){
for(int j = 0;j < 9;j = j + 3){
for(int num = 1;num <= 9;++num){
int x = -1, y = -1, numcnt = 0;
bool stop = false;
for(int indexx = i;indexx < i + 3;++indexx)
for(int indexy = j;indexy < j + 3;++indexy){
if(shudu[indexx][indexy] == num){
stop = true;
break;
}
list<int>::iterator it = find(t[indexx][indexy].begin(), t[indexx][indexy].end(), num);
if(it != t[indexx][indexy].end()){
x = indexx;
y = indexy;
numcnt++;
}
}
if(stop) continue;
if(numcnt == 1){
t[x][y].clear();
t[x][y].push_back(num);
shudu[x][y] = num;
if(freshHelperData(shudu, t, x, y)<0) return -1;
hasChanged = true;
}
}
}
}
return hasChanged ? 1 : 0;
}
void initShudu(vector<vector<char>>& board, vector<vector<int>>& shudu){
for(int i = 0;i < 9; ++i){
vector<int> vec;
for(int j = 0;j < 9; ++j){
vec.push_back(board[i][j] == '.' ? 0 : board[i][j] - '0');
}
shudu.push_back(vec);
}
}
void solveSudoku(vector<vector<char>>& board) {
vector<vector<int>> shudu;
initShudu(board, shudu);
vector<vector<list<int>>> t;
initHelpData(t);
updateHelpData(shudu, t);
int count = 0;
stack<ShuDuIndex> stkIndex;
stack<vector<vector<int>> > stkShuDu;
stack<vector<vector<list<int>>> > stkT;
while(count++ < 1000){
int changeStatus = changeShuDu(shudu, t);
int indexx = -1, indexy = -1, indexz = -1, listsize = 100;
if(changeStatus == 1) continue;
else if(changeStatus == -1){
while(true){
if(stkShuDu.empty()){
//ut << "all choice invalid stack empty fail" << endl;
return ;
}
shudu = stkShuDu.top();
t = stkT.top();
ShuDuIndex sd = stkIndex.top();
if(t[sd.i][sd.j].size() == sd.index+1){
//cout << "choice invalid goto next stack" << endl;
stkShuDu.pop();
stkT.pop();
stkIndex.pop();
continue;
}
stkIndex.pop();
sd.index = sd.index+1;
stkIndex.push(sd);
indexx = sd.i;
indexy = sd.j;
indexz = sd.index;
break;
}
}
else{
if(HasFinished(shudu)) break;
for(int i = 0;i < 9; ++i){
for(int j = 0;j < 9; ++j){
if(shudu[i][j] == 0 && t[i][j].size() < listsize){
indexx = i, indexy = j, listsize = t[i][j].size();
}
}
}
ShuDuIndex sd;
sd.i = indexx;
sd.j = indexy;
sd.index = 0;
indexz = 0;
stkShuDu.push(shudu);
stkT.push(t);
stkIndex.push(sd);
//cout << "push data to stack" << endl;
}
int num = -1;
list<int>::iterator it = t[indexx][indexy].begin();
for(int i = 0;i < indexz; ++i) ++it;
num = *it;
shudu[indexx][indexy] = num;
t[indexx][indexy].clear();
t[indexx][indexy].push_back(num);
}
for(int i = 0;i < 9; ++i)
for(int j = 0;j < 9; ++j)
board[i][j] = '0' + shudu[i][j];
}
};
更新会同步在我的网站更新(https://zergzerg.cn/notes/webnotes/leetcode/index.html)