想要精通算法和SQL的成长之路 - 解数独
创始人
2024-03-30 20:24:32

想要精通算法和SQL的成长之路 - 解数独

  • 一. 解数独
    • 1.1 校验函数
    • 1.2 回溯函数

一. 解数独

原题链接

编写一个程序,通过填充空格来解决数独问题。数独的解法需遵循如下规则:

  • 数字 1-9 在每一行只能出现一次。
  • 数字 1-9 在每一列只能出现一次。
  • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 ‘.’ 表示。案例:
在这里插入图片描述
结果如下:
在这里插入图片描述

数独这道题目,首先想到的还是回溯法,本质就是:

  1. 在9x9的格子中,从左上角开始,从左往右,从上到下开始遍历。
  2. 不断地往格子中填入数字。填充数字的同时,判断是否满足数独的特性。
  3. 不满足,则回溯。从上一轮继续填充下一个数字。直到填充完毕。

那么这个题目的关键就是:如何判断是否满足数独的特性。

1.1 校验函数

传入的参数:我们要塞入的数字、对应的行、列下标。

目的:检查行、列、所在的3x3格子内无重复数字。

代码如下:

public boolean isValid(char[][] board, int row, int col, char val) {// 检查行for (int i = 0; i < 9; i++) {if (board[row][i] == val) {return false;}}// 检查列for (int i = 0; i < 9; i++) {if (board[i][col] == val) {return false;}}// 检查 3x3int tmpRow = (row / 3) * 3;// 要检查的3x3格子的起始行int tmpCol = (col / 3) * 3;// 要检查的3x3格子的起始列for (int i = tmpRow; i < tmpRow + 3; i++) {for (int j = tmpCol; j < tmpCol + 3; j++) {if (board[i][j] == val) {return false;}}}return true;
}

举个例子,我们想要在(4,7)这个格子中塞入一个值。那么它所在的3x3格子的起始坐标就是:

  • 行坐标:(4/3)*3 = 3。
  • 纵坐标:(7/3)*3 = 6。

就是如图所在位置开始遍历(红色圈内)
在这里插入图片描述

1.2 回溯函数

那么我们在填充数字的时候,肯定是遍历每一个格子的。因此就会有一个双重for循环。

又因为我们填充的数字范围是[1,9],因此这里又有一层 for 循环。 总共三层。 代码如下:

public boolean backtrack(char[][] board) {// 双层循环,遍历所有格子for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {// 已经被填过的不算if (board[i][j] != '.') {continue;}// 第三个for循环。对没填过数独的格子进行遍历,填充的数字在[1,9]范围内for (char k = '1'; k <= '9'; k++) {// 只有合法的,再能插入数字if (isValid(board, i, j, k)) {// 填充board[i][j] = k;// 填充下一个数字,如果填充完毕了,直接返回if (backtrack(board)) {return true;}// 回溯board[i][j] = '.';}}// 因为这一个格子尝试填充了1,9,如果上面没有提前return true// 说明是个不合法的数独。只能返回false,结束遍历return false;}}// 结束遍历,每个格子都填好了,返回truereturn true;
}

最终代码:

public class Test37 {public void solveSudoku(char[][] board) {backtrack(board);}public boolean backtrack(char[][] board) {for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {// 已经被填过的不算if (board[i][j] != '.') {continue;}// 对没填过数独的格子进行遍历for (char k = '1'; k <= '9'; k++) {// 只有合法的,再能插入数字if (isValid(board, i, j, k)) {board[i][j] = k;if (backtrack(board)) {return true;}board[i][j] = '.';}}return false;}}return true;}public boolean isValid(char[][] board, int row, int col, char val) {// 检查行for (int i = 0; i < 9; i++) {if (board[row][i] == val) {return false;}}// 检查列for (int i = 0; i < 9; i++) {if (board[i][col] == val) {return false;}}// 检查 3x3int tmpRow = (row / 3) * 3;// 3x3格子 的行int tmpCol = (col / 3) * 3;// 3x3格子 的列for (int i = tmpRow; i < tmpRow + 3; i++) {for (int j = tmpCol; j < tmpCol + 3; j++) {if (board[i][j] == val) {return false;}}}return true;}
}

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...