自己的解法
我看到这个题目的时候想法就很简单,他三个要求有效:行,列,九宫格。
那我就每一个检查一遍不就行了。
这里是我最开始的版本,也花了不少时间,主要代码能力还是欠缺。
class Solution {
bool isValid(vector<char> &cvec){
map<char,int> s;
for(auto c:cvec){
if(isdigit(c)){
++s[c];
if(s[c]>1){return false;}
}
}
return true;
}
public:
bool isValidSudoku(vector<vector<char>>& board) {
//行
int h=1;
for(auto v:board){
h=h*isValid(v);
}
//列
int l=1;
for(int i=0;i<9;i++){
vector<char> lv;
for(int j=0;j<9;j++){
lv.push_back(board[j][i]);
}
l = l*isValid(lv);
}
//九宫格
int n=1;
for(int i=0;i<9;++i){
vector<char> nv;
for(int x=(i%3)*3;x<(i%3)*3+3;x++){
for(int y=i/3*3;y<i/3*3+3;y++){
nv.push_back(board[x][y]);
}
}
n=n*isValid(nv);
}
return true;
}
};
当然这个存在很多问题,不过总算跑通了。
首先我写了一个判断一个vector里面是否是有效的,之后是依靠每一次检查结果累乘,因为又一次无效,结果就会乘上0,最后结果也会是0。
不过这个方法很繁琐,而且也没必要每次都检查,只要检查出错误,直接返回就行了。而且这个累乘的方法,可读性不太行。
后面修改了一下
class Solution {
bool isValid(vector<char> &cvec){
map<char,int> s;
for(auto c:cvec){
if(isdigit(c)){
++s[c];
if(s[c]>1){return false;}
}
}
return true;
}
public:
bool isValidSudoku(vector<vector<char>>& board) {
//行
int h=1;
for(auto v:board){
if (!isValid(v)) return false;
}
//列
int l=1;
for(int i=0;i<9;i++){
vector<char> lv;
for(int j=0;j<9;j++){
lv.push_back(board[j][i]);
}
if (!isValid(lv)) return false;
}
//九宫格
int n=1;
for(int i=0;i<9;++i){
vector<char> nv;
for(int x=(i%3)*3;x<(i%3)*3+3;x++){
for(int y=i/3*3;y<i/3*3+3;y++){
nv.push_back(board[x][y]);
}
}
if (!isValid(nv)) return false;
}
return true;
}
};
这样的改动不仅修正了错误,还提高了代码的效率和可读性。
官方解题
接下来我们看看官方解题
官方的解题是用了一次遍历,这个方法很好,想法是对每一(行,列,九宫格)出现的数进行计数。最后只要有一个计数>1,就说明无效。
使用哈希表记录每一行、每一列和每一个小九宫格中,每个数字出现的次数。只需要遍历数独一次,在遍历的过程中更新哈希表中的计数,并判断是否满足有效的数独的条件即可
这个方法更加简洁高效相比于我的解法。
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
int rows[9][9];
int columns[9][9];
int subboxes[3][3][9];
memset(rows,0,sizeof(rows));
memset(columns,0,sizeof(columns));
memset(subboxes,0,sizeof(subboxes));
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
char c = board[i][j];
if (c != '.') {
int index = c - '0' - 1;
rows[i][index]++;
columns[j][index]++;
subboxes[i / 3][j / 3][index]++;
if (rows[i][index] > 1 || columns[j][index] > 1 || subboxes[i / 3][j / 3][index] > 1) {
return false;
}
}
}
}
return true;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/valid-sudoku/solutions/1001859/you-xiao-de-shu-du-by-leetcode-solution-50m6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在C++中,
memset
函数是用来将一段内存中的所有字节都设置为特定的值的函数,通常用于初始化数组或结构体。当你写memset(rows, 0, sizeof(rows));
目的是将名为rows
的数组中的所有元素初始化为0。
综上,还需多练。/(ㄒoㄒ)/~~