栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

leetcode 37 解数独

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

leetcode 37 解数独

前言

题目:37. 解数独

参考题解:解数独-代码随想录


提交代码

记得以前杂志的后面,会附录些数独的题目。现在,我们用代码来求解。

思路:每个空格格,在遇到的时候,可能有不同的填充值。空格轮使用不同的值尝试。尝试失败,进行回溯,重新尝试。

不难哈,我在范围上多写了一个减一,导致大量的时间用于调试。

#include 
#include 
#include 

using namespace std;

class Solution {
public:
    void canAppear(const vector>& board, pair loc, vector& can_appr){
        // 给定数独,和某个位置。将位置目前可以填充的数字放入can_appr中

        set appred; // 保存所在行,列,正方形内出现过的数字
        
        // 正方形内出现过的数字
        pair upper_left_corner(loc.first/3*3,loc.second/3*3);
        for(int i=upper_left_corner.first; i nextLoc(const vector>& board,pair loc){
        // 当前位置的下一个位置
        if(loc.second nextPointLoc(const vector>& board,pair loc){
        // 当前位置的下一个'.'位置。或者,是超出范围的最后一行的下一行开头位置
        pair next_loc = nextLoc(board,loc);
        while(next_loc.first>& board,pair loc){
        // 题目数据 保证 输入数独仅有一个解
        // 从上向下,从左到右,填充数独

        // 填充完毕,返回
        if(loc.first == board.size())
            return true;
        

        if(board[loc.first][loc.second] != '.') // 已经存在数字,跳转到需要填充的位置。回溯过程中,仅开头可能会使用一次
            loc = nextPointLoc(board,loc); 
                
        vector can_appr;
        canAppear(board,loc,can_appr); // 统计目前当前位置可以出现的数字
        for(int k=0; k next_loc = nextPointLoc(board,loc); // 计算下一个需要填充的位置

            // for(auto vec : board){
            //     for(auto ch : vec)
            //         cout<>& board) {
        backTracking(board,{0,0});
    }
};


int main(void){
    vector> board = {{'5','3','.','.','7','.','.','.','.'},
                                  {'6','.','.','1','9','5','.','.','.'},
                                  {'.','9','8','.','.','.','.','6','.'},
                                  {'8','.','.','.','6','.','.','.','3'},
                                  {'4','.','.','8','.','3','.','.','1'},
                                  {'7','.','.','.','2','.','.','.','6'},
                                  {'.','6','.','.','.','.','2','8','.'},
                                  {'.','.','.','4','1','9','.','.','5'},
                                  {'.','.','.','.','8','.','.','7','9'}};
    Solution s;
    s.solveSudoku(board);
    for(auto vec : board){
        for(auto ch : vec)
            cout< 

参考题解的大体思路和上面相同。但是,参考题解比我的代码质量相对要好。

下面代码来自参考题解。

class Solution {
private:
bool backtracking(vector>& board) {
    for (int i = 0; i < board.size(); i++) {        // 遍历行
        for (int j = 0; j < board[0].size(); j++) { // 遍历列
            if (board[i][j] != '.') continue;
            for (char k = '1'; k <= '9'; k++) {     // (i, j) 这个位置放k是否合适
                if (isValid(i, j, k, board)) {
                    board[i][j] = k;                // 放置k
                    if (backtracking(board)) return true; // 如果找到合适一组立刻返回
                    board[i][j] = '.';              // 回溯,撤销k
                }
            }
            return false;                           // 9个数都试完了,都不行,那么就返回false
        }
    }
    return true; // 遍历完没有返回false,说明找到了合适棋盘位置了
}
bool isValid(int row, int col, char val, vector>& board) {
    for (int i = 0; i < 9; i++) { // 判断行里是否重复
        if (board[row][i] == val) {
            return false;
        }
    }
    for (int j = 0; j < 9; j++) { // 判断列里是否重复
        if (board[j][col] == val) {
            return false;
        }
    }
    int startRow = (row / 3) * 3;
    int startCol = (col / 3) * 3;
    for (int i = startRow; i < startRow + 3; i++) { // 判断9方格里是否重复
        for (int j = startCol; j < startCol + 3; j++) {
            if (board[i][j] == val ) {
                return false;
            }
        }
    }
    return true;
}
public:
    void solveSudoku(vector>& board) {
        backtracking(board);
    }
};

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/289735.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号