加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

[LeetCode] Sudoku Solver

发布时间:2020-12-13 20:08:23 所属栏目:PHP教程 来源:网络整理
导读:Sudoku Solver Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by the character '.' . You may assume that there will be only one unique solution. A sudoku puzzle... ...and its solution numbers

Sudoku Solver

Write a program to solve a Sudoku puzzle by filling the empty cells.

Empty cells are indicated by the character '.'.

You may assume that there will be only one unique solution.


A sudoku puzzle...


...and its solution numbers marked in red.

解题思路:

之前没有玩过数独,因而就上网恶补了1下。因而我就堕入了1个误区,数独的几种技能想用程序完全实现出来。因而乎,纠结了很久。本来用程序员思惟来做非常容易的,就是回溯而已。我实现了唯1余数法和行列摒除法,若不能继续求解,则用暴力法。代码以下。57ms。

class Solution { public: void solveSudoku(vector<vector<char> > &board) { set<int> allCan({ 1,2,3,4,5,6,7,8,9 }); map<int,set<int>> candidates; map<int,set<int>> rowLeft; //某1行还剩下哪些数 map<int,set<int>> colLeft; //某1列还剩下哪些数 for (int i = 0; i < 9; i++){ rowLeft[i] = allCan; colLeft[i] = allCan; } for (int i = 0; i<9; i++){ for (int j = 0; j<9; j++){ if (board[i][j] == '.'){ candidates[get1D(i,j)] = allCan; prunning(board,i,j,candidates); } else{ rowLeft[i].erase(board[i][j]-'0'); colLeft[j].erase(board[i][j] - '0'); } } } while (candidates.size()>0){ int unknowNumber = candidates.size(); //唯1余数法 { for (map<int,set<int>>::iterator it = candidates.begin(); it != candidates.end();){ if (it->second.size() == 1){ int i = get2Di(it->first); int j = get2Dj(it->first); board[i][j] = *(it->second.begin()) + '0'; rowLeft[i].erase(board[i][j] - '0'); colLeft[j].erase(board[i][j] - '0'); candidates.erase(it++); } else{ it++; } } for (int i = 0; i<9; i++){ for (int j = 0; j<9; j++){ if (board[i][j] == '.'){ prunning(board,candidates); } } } } //行摒除法 { for (int i = 0; i < 9; i++){ for (set<int>::iterator it = rowLeft[i].begin(); it != rowLeft[i].end();){ int pos = ⑴; bool onlyOne = true; for (int j = 0; j < 9; j++){ int index = get1D(i,j); if (candidates.find(index) != candidates.end() && candidates[index].find(*it) != candidates[index].end()){ if (pos >= 0){ onlyOne = false; break; } pos = j; } } if (onlyOne&&pos >= 0){ board[i][pos] = *it + '0'; colLeft[pos].erase(*it); rowLeft[i].erase(it++); candidates.erase(get1D(i,pos)); } else{ it++; } } } for (int i = 0; i < 9; i++){ for (int j = 0; j < 9; j++){ if (board[i][j] == '.'){ prunning(board,candidates); } } } } //列摒除法 { for (int j = 0; j < 9; j++){ for (set<int>::iterator it = colLeft[j].begin(); it != colLeft[j].end();){ int pos = ⑴; bool onlyOne = true; for (int i = 0; i < 9; i++){ int index = get1D(i,j); if (candidates.find(index) != candidates.end() && candidates[index].find(*it) != candidates[index].end()){ if (pos >= 0){ onlyOne = false; break; } pos = i; } } if (onlyOne&&pos >= 0){ board[pos][j] = *it + '0'; rowLeft[pos].erase(*it); colLeft[j].erase(it++); candidates.erase(get1D(pos,j)); } else{ it++; } } } for (int i = 0; i<9; i++){ for (int j = 0; j<9; j++){ if (board[i][j] == '.'){ prunning(board,candidates); } } } } if (unknowNumber == candidates.size()){ break; } } //若仍未解答出来,则暴力枚举 if (candidates.size() > 0){ dfsCheck(board,candidates,candidates.begin()); } } bool dfsCheck(vector<vector<char> > &board,map<int,set<int>> &candidates,set<int>>::iterator it){ if (it == candidates.end()){ return true; } int i = get2Di(it->first); int j = get2Dj(it->first); for (set<int>::iterator setIt = it->second.begin(); setIt != it->second.end(); setIt++){ board[i][j] = *setIt+'0'; it++; if (isValidSudoku(board) && dfsCheck(board,it)){ return true; } it--; board[i][j] = '.'; } } private: int get1D(int i,int j){ return i * 9 + j; } int get2Di(int index){ return index / 9; } int get2Dj(int index){ return index % 9; } void prunning(vector<vector<char> > &board,int i,int j,set<int>> &candidates){ pruningGrid(board,candidates); pruningRow(board,candidates); pruningColumn(board,candidates); } void pruningGrid(vector<vector<char> > &board,set<int>> &candidates){ int index = get1D(i,j); while (i % 3 != 0){ i--; } while (j % 3 != 0){ j--; } for (int m = i; m < i + 3; m++){ for (int n = j; n < j + 3; n++){ if (board[m][n] != '.'){ candidates[index].erase(board[m][n] - '0'); } } } } void pruningRow(vector<vector<char> > &board,j); for (int m = 0; m < 9; m++){ if (board[i][m] != '.'){ candidates[index].erase(board[i][m] - '0'); } } } void pruningColumn(vector<vector<char> > &board,j); for (int m = 0; m < 9; m++){ if (board[m][j] != '.'){ candidates[index].erase(board[m][j] - '0'); } } } bool isValidSudoku(vector<vector<char>>& board) { //验证每行是不是有效 for (int i = 0; i<9; i++){ if (!checkRowValid(board,i)){ return false; } } //验证每列是不是有效 for (int i = 0; i<9; i++){ if (!checkColumnValid(board,i)){ return false; } } //验证每格是不是有效 for (int i = 0; i<9; i = i + 3){ for (int j = 0; j<9; j = j + 3){ if (!checkGridValid(board,j)){ return false; } } } return true; } //验证每一个格是不是有效,传入的是左上角的下标 bool checkGridValid(vector<vector<char>>& board,int m,int n){ bool flag[9]; memset(flag,sizeof(bool)* 9); for (int i = m; i<m + 3; i++){ for (int j = n; j<n + 3; j++){ if (board[i][j] == '.'){ continue; } if (flag[board[i][j] - '1']){ return false; } flag[board[i][j] - '1'] = true; } } return true; } //验证每行是不是有效,传入的是行号 bool checkRowValid(vector<vector<char>>& board,int m){ bool flag[9]; memset(flag,sizeof(bool)* 9); for (int i = 0; i<9; i++){ if (board[m][i] == '.'){ continue; } if (flag[board[m][i] - '1']){ return false; } flag[board[m][i] - '1'] = true; } return true; } //验证每列是不是有效,传入的是列号 bool checkColumnValid(vector<vector<char>>& board,sizeof(bool)* 9); for (int i = 0; i<9; i++){ if (board[i][n] == '.'){ continue; } if (flag[board[i][n] - '1']){ return false; } flag[board[i][n] - '1'] = true; } return true; } };
只包括唯1余数法。113ms

class Solution { public: void solveSudoku(vector<vector<char> > &board) { set<int> allCan({ 1,set<int>> candidates; for (int i = 0; i<9; i++){ for (int j = 0; j<9; j++){ if (board[i][j] == '.'){ candidates[get1D(i,candidates); } } } while (candidates.size()>0){ int unknowNumber = candidates.size(); //唯1余数法 for (map<int,set<int>>::iterator it = candidates.begin(); it != candidates.end();){ if (it->second.size() == 1){ int i = get2Di(it->first); int j = get2Dj(it->first); board[i][j] = *(it->second.begin()) + '0'; candidates.erase(it++); } else{ it++; } } for (int i = 0; i<9; i++){ for (int j = 0; j<9; j++){ if (board[i][j] == '.'){ prunning(board,candidates); } } } if (unknowNumber == candidates.size()){ break; } } //若仍未解答出来,则暴力枚举 if (candidates.size() > 0){ dfsCheck(board,int j){ return i * 9 + j; } int get2Di(int index){ return index / 9; } int get2Dj(int index){ return index % 9; } void prunning(vector<vector<char> > &board,sizeof(bool)* 9); for (int i = 0; i<9; i++){ if (board[i][n] == '.'){ continue; } if (flag[board[i][n] - '1']){ return false; } flag[board[i][n] - '1'] = true; } return true; } };


(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读