LeetCode系列之【37. 解数独】C++ 每天一道leetcode!

目录(快速导航)

题目描述

视频讲解 https://www.bilibili.com/video/av66851453/

思路

代码


题目描述:

题目链接:https://leetcode-cn.com/problems/longest-valid-parentheses/

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则:

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。

Note:

  • 给定的数独序列只包含数字 1-9 和字符 '.' 。
  • 你可以假设给定的数独只有唯一解。
  • 给定数独永远是 9x9 形式的。

视频讲解

https://www.bilibili.com/video/av66851453/


思路:

  1. 回溯,把所有情况试一遍;

  2. 当填写第i行,第j列的元素时,需要知道其对应的行,列,块中,1-9数字的使用情况,从而选用不同的数字,因为矩阵的大小一直都是9*9,所以我们新建row[9][9],col[9][9],block[9][9],来存储,注意:这三个矩阵,第一维度表示所在的行、列、块索引,第二维度对应1-9数字,如:row[1][2]=1,表示第1行中的2已经被使用,从第0行开始
  3. 块的index的计算方法:

        

 

步骤:

  1. 使用board来初始化row,col,block;
  2. 调用recall(i,j,board)来回溯填充;
  3. recall里面的事: 
  • 如果i到达9,填充完毕;
  • 如果board[i][j]为数字,那么直接到下一个空格;
  • 如果board[i][j]为‘.’,那么从1-9开始遍历填充,首先查看数字是否在row[i],col[j],block[index]中使用,如果都没有使用,就填充该数字,更新row,col和block,同时继续下一个空格。
  • 检测是否填充完毕,如果没有,就回溯。

代码:

class Solution {
public:
    bool solved = 0,row[9][9], col[9][9], block[9][9];
    void recall(vector<vector<char>>& board, int i, int j) {
        if (i == 9) { 
            solved = 1;
            return;
        }
        // 如果有数字
        if (board[i][j] != '.') {
            if (j < 8) recall(board, i, j + 1);
            else recall(board, i + 1, 0);
        }
        else {
            int index = (i / 3) * 3 + j / 3;
            for (int k = 1;k <= 9;k++) {
                // 如果在行、列、块 中都没有使用
                if (!row[i][k - 1] && !col[j][k - 1] && !block[index][k - 1]) {
                    board[i][j] = k + '0';
                    row[i][k - 1] = col[j][k - 1] = block[index][k - 1] = 1;
                    // 继续下一个
                    if (j < 8) recall(board, i, j + 1);
                    else recall(board, i + 1, 0);
                    // 如果没有解决 那么回溯
                    if (!solved) {
                        board[i][j] = '.';
                        row[i][k - 1] = col[j][k - 1] = block[index][k - 1] = 0;
                    }
                }
            }
        }
    }

    void solveSudoku(vector<vector<char>>& board) {
        // 初始化为false
        memset(row, 0, sizeof(row));
        memset(col, 0, sizeof(col));
        memset(block, 0, sizeof(block));

        // 将使用的对应数值置为true
        for (int i = 0; i < 9; i++){
            for (int j = 0;j < 9;j++) {
                if (board[i][j] == '.') continue;
                int index = (i / 3) * 3 + j / 3;
                int num = board[i][j] - '0';
                row[i][num - 1] = col[j][num - 1] = block[index][num - 1] = 1;
            }
        }
        recall(board, 0, 0);
    }

};

一起加油!!刷题!!

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值