diff --git a/solutions/36. Valid Sudoku.md b/solutions/36. Valid Sudoku.md new file mode 100644 index 0000000..fe4e55d --- /dev/null +++ b/solutions/36. Valid Sudoku.md @@ -0,0 +1,135 @@ +# [36. Valid Sudoku](https://leetcode.com/problems/valid-sudoku/) +# 思路 +题意就是要求判断给定的board是否是一个合法的数独。 +## 思路一 +开辟一个大小为9的数组mp(实际代码中为了直接用1-9的下标所以开的大小为10的数组,下同),遍历三次数独,分别判断row、column、sub_box是否合法就完事。 + +## 思路二 +思路一在每次循环后都要讲数组mp清零,也可以考虑用空间换时间的思路,多开几个一次性的数组,这样就不用清零了。 +注意第i行第j列(0 <= i,j <=2)的sub_box是第`i*3 + j`个sub_box。 + +## 思路三 +前面两种思路都需要对board遍历三次,所以代码写得很冗长,一点都不elegant,其实一次遍历就够了。 +需要注意的是第i行第j列(0 <= i,j <= 8)的元素所在的sub_box是第`3 * (i/3) + j/3`个,注意`i/3`需要加括号。(这里的i/3和j/3就是对应的思路二中的i,j) + +# C++ +## 思路一 +``` C++ +class Solution { +private: + bool sub_box_is_valid(int x, int y, const vector>& board, vector&mp){ + // x和y是这个sub_box左上角的坐标 + for(int k = 1; k <= 9; k++) mp[k] = 0; + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + if(board[i+x][j+y] == '.') continue; + if(mp[board[i+x][j+y] - '0'] > 0) return false; + mp[board[i+x][j+y] - '0']++; + } + } + return true; + } + +public: + bool isValidSudoku(vector>& board) { + vectormp(10, 0); + // 判断行 + for(int i = 0; i < 9; i++){ + for(int j = 0; j < 9; j++){ + if(board[i][j] == '.') continue; + if(mp[board[i][j] - '0'] > 0) return false; + mp[board[i][j] - '0']++; + } + for(int k = 1; k <= 9; k++) mp[k] = 0; // 清零数组 + } + + // 判断列 + for(int j = 0; j < 9; j++){ + for(int i = 0; i < 9; i++){ + if(board[i][j] == '.') continue; + if(mp[board[i][j] - '0'] > 0) return false; + mp[board[i][j] - '0']++; + } + for(int k = 1; k <= 9; k++) mp[k] = 0; + } + // 判断sub_box + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + if(sub_box_is_valid(i*3, j*3, board, mp)) continue; + return false; + } + } + return true; + } +}; +``` +## 思路二 +``` C++ +class Solution { +private: + bool sub_box_is_valid(int x, int y, const vector>& board, vector&mp){ + //for(int k = 1; k <= 9; k++) mp[k] = 0; + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + if(board[i+x][j+y] == '.') continue; + if(mp[board[i+x][j+y] - '0'] > 0) return false; + mp[board[i+x][j+y] - '0']++; + } + } + return true; + } + +public: + bool isValidSudoku(vector>& board) { + vector>mp1(10, vector(10, 0)); + vector>mp2(10, vector(10, 0)); + vector>mp3(10, vector(10, 0)); + for(int i = 0; i < 9; i++){ + for(int j = 0; j < 9; j++){ + if(board[i][j] == '.') continue; + if(mp1[i][board[i][j] - '0'] > 0) return false; + mp1[i][board[i][j] - '0']++; + } + } + + for(int j = 0; j < 9; j++){ + for(int i = 0; i < 9; i++){ + if(board[i][j] == '.') continue; + if(mp2[j][board[i][j] - '0'] > 0) return false; + mp2[j][board[i][j] - '0']++; + } + } + + for(int i = 0; i < 3; i++){ + for(int j = 0; j < 3; j++){ + // 第i行第j列(0 <= i,j <=2)的sub_box是第i*3 + j个sub_box。 + if(sub_box_is_valid(i*3, j*3, board, mp3[i*3 + j])) continue; + return false; + } + } + return true; + } +}; +``` +## 思路三 +``` C++ +class Solution { +public: + bool isValidSudoku(vector>& board) { + // vector>mp1(10, vector(10, 0)); + int mp1[10][10] = {0}, mp2[10][10] = {0}, mp3[10][10] = {0}; + int n, sub_box_index; + for(int i = 0; i < 9; i++){ + for(int j = 0; j < 9; j++){ + if(board[i][j] == '.') continue; + n = board[i][j] - '0'; + sub_box_index = 3 * (i/3) + j/3; // 注意i/3需要加括号 + if(mp1[i][n] || mp2[j][n] || mp3[sub_box_index][n]) return false; + mp1[i][n] = mp2[j][n] = mp3[sub_box_index][n] = 1; + } + } + + return true; + } +}; +```