leecode题目36

自己的解法

我看到这个题目的时候想法就很简单,他三个要求有效:行,列,九宫格

那我就每一个检查一遍不就行了。

这里是我最开始的版本,也花了不少时间,主要代码能力还是欠缺。

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ㄒ)/~~

### LeetCode 拓扑排序经典题目解析 #### 1. **LeetCode 207. 课程表** 此题的核心在于判断给定的课程安排是否存在一种有效的拓扑排序[^1]。如果能够找到这样的一种排列,则表示不存在环路,课程可以顺利完成;反之则不可行。具体实现过程中需要用到邻接矩阵或邻接链表来构建图结构,并通过Kahn算法(基于BFS)或者深度优先搜索(DFS)的方法来进行检测是否有环的存在。 ```cpp // Kahn's Algorithm Example Code Snippet for Problem 207 vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) { vector<vector<int>> adj(numCourses); vector<int> indegree(numCourses, 0); for(auto &p : prerequisites){ adj[p[1]].push_back(p[0]); ++indegree[p[0]]; } queue<int> q; for(int i=0;i<numCourses;++i){ if(indegree[i]==0)q.push(i); } vector<int> res; while(!q.empty()){ int cur=q.front();q.pop(); res.push_back(cur); for(auto next:adj[cur]){ --indegree[next]; if(indegree[next]==0)q.push(next); } } return res.size()==numCourses?res:vector<int>(); } ``` --- #### 2. **LeetCode 210. 课程表 II** 这是对前一问题的进一步深化,不仅要求判定是否存在有效路径,还需要返回具体的选课顺序[^2]。同样可以通过拓扑排序的思想解决这个问题,区别只在于最后的结果呈现形式有所改变——当且仅当所有节点都被遍历过后才认为找到了合适的解决方案。 --- #### 3. **LeetCode 269. 外星语言词典** 虽然表面上看这道题似乎与字符串处理更加相关,但实际上它的本质依然是一个典型的拓扑排序应用场景之一[^3]。通过对单词之间的字母比较建立起字符间的相对大小关系网之后,就可以运用同样的技巧去还原整个外星文字母表应有的正确次序了。 --- #### 4. **其他涉及拓扑排序的相关练习建议** 除了以上列举出来的几个较为经典的案例之外,还有不少其他的习题也值得大家尝试练习以便更好地理解和掌握这一知识点的实际运用能力。比如像[ArcWing]848那样的基础入门级训练项目就非常适合初学者用来熟悉基本概念和技术要点[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值