目录(快速导航)
题目描述
视频讲解 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/
思路:
-
回溯,把所有情况试一遍;
- 当填写第i行,第j列的元素时,需要知道其对应的行,列,块中,1-9数字的使用情况,从而选用不同的数字,因为矩阵的大小一直都是9*9,所以我们新建row[9][9],col[9][9],block[9][9],来存储,注意:这三个矩阵,第一维度表示所在的行、列、块索引,第二维度对应1-9数字,如:row[1][2]=1,表示第1行中的2已经被使用,从第0行开始;
- 块的index的计算方法:
步骤:
- 使用board来初始化row,col,block;
- 调用recall(i,j,board)来回溯填充;
- 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);
}
};