leetcode 37. 解数独 思考分析

目录

    • 题目
    • 核心思路的不断细化
      • 1、核心框架
      • 2、考虑到每个位置的工作
      • 3、考虑到到达最后一列、该位置的数已经预置的情况
      • 4、判断是否符合规则的函数
      • 5、确定递归终止条件+确定函数返回值
    • AC代码

题目

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

1、数字 1-9 在每一行只能出现一次。
2、数字 1-9 在每一列只能出现一次。
3、数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

空白格用 ‘.’ 表示。

一个数独。
答案被标成红色。
提示:

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

核心思路的不断细化

算法的核心思路就是对每一个空着的格子穷举 1 到 9,如果遇到不合法的数字(在同一行或同一列或同一个 3×3 的区域中存在相同的数字)则跳过,如果找到一个合法的数字,则继续穷举下一个空格子。
写出核心框架:

1、核心框架

void solveSudoku(vector<vector<char>>& board) {backtrack(board, 0, 0);
}void backtrack(vector<vector<char>>& board, int hang, int lie) {// 就是对棋盘的每个位置进行穷举for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {// 做选择backtrack(board, i, j);// 撤销选择}}
}

2、考虑到每个位置的工作

对于每个位置有1~9的选择,这样就变成了3重嵌套循环。

void backtrack(vector<vector<char>>& board, int hang, int lie) {// 就是对每个位置进行穷举for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {for (char ch = '1'; ch <= '9'; ch++) {// 做选择board[i][j] = ch;// 继续穷举下一列,backtrack(board, i, j + 1);// 撤销选择board[i][j] = '.';}}}
}

3、考虑到到达最后一列、该位置的数已经预置的情况

1、当lie到达超过最后一个索引时,转为增加hang开始穷举下一行。
2、如果当前位置元素不为“.”,那么跳过即可。
3、穷举的时候如果遇到符合规则的数字,填入,否则跳过。

void backtrack(vector<vector<char>>& board, int hang, int lie) {if(lie==9){backtrack(board, hang+1, 0);}// 就是对每个位置进行穷举for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {// 如果该位置是预设的数字,不用我们操心if (board[i][j] != '.') {backtrack(board, i, j + 1);return;} //如果不是预置的数字for (char ch = '1'; ch <= '9'; ch++) {// 如果遇到符合规则的数字,填入if (isValid(board, i, j, ch)){// 做选择board[i][j] = ch;// 继续穷举下一列,backtrack(board, i, j + 1);// 撤销选择board[i][j] = '.';}}}}
}

4、判断是否符合规则的函数

规则如下:

1、数字 1-9 在每一行只能出现一次。
2、数字 1-9 在每一列只能出现一次。
3、数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

翻译成函数:
注意这里对第3个规则的描述:

// 判断 board[i][j] 是否可以填入 n
bool isValid(vector<vector<char>>& board, int hang, int lie, char n) {for (int i = 0; i < 9; i++) {// 判断行是否存在重复if (board[hang][i] == n) return false;// 判断列是否存在重复if (board[i][lie] == n) return false;// 判断 3 x 3 方框是否存在重复if (board[(hang/3)*3 + i/3][(lie/3)*3 + i%3] == n)return false;}return true;
}

下面是这个式子的含义,并且将i=0~8模拟了一下:
在这里插入图片描述

5、确定递归终止条件+确定函数返回值

如果递归完最后一行,那么我们就可以返回我们的结果了。
如果找到一个解我们的任务就结束了,本题并没有要求找到所有解。
如果一个位置遍历完所有数字,都不符合,这说明此路不通,应该及时返回false。
如果每个位置都遍历过了,结果都没有返回true,说明,这个数独棋盘没有解,返回false。
所以使用bool类型的值作为返回值:

if(hang == 9) return true;

完整的回溯函数代码应该如下:

bool backtrack(vector<vector<char>>& board, int hang, int lie) {//遍历完这一行最后一列,转而遍历下一行if(lie==9){return backtrack(board, hang+1, 0);}//找到一个解,返回if(hang == 9) return true;// 就是对每个位置进行穷举for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {// 如果该位置是预设的数字,不用我们操心if (board[i][j] != '.') {return backtrack(board, i, j + 1);} //如果不是预置的数字for (char ch = '1'; ch <= '9'; ch++) {// 如果遇到符合规则的数字,填入if (isValid(board, i, j, ch)){// 做选择board[i][j] = ch;// 继续穷举下一列,如果找到了一个解,立即结束if(backtrack(board, i, j + 1) == true) return true;// 撤销选择board[i][j] = '.';}}// 穷举完 1~9,依然没有找到可行解,此路不通return false;}}return false;
}

AC代码

class Solution {
public:// 判断 board[i][j] 是否可以填入 nbool isValid(vector<vector<char>>& board, int hang, int lie, char n) {for (int i = 0; i < 9; i++) {// 判断行是否存在重复if (board[hang][i] == n) return false;// 判断列是否存在重复if (board[i][lie] == n) return false;// 判断 3 x 3 方框是否存在重复if (board[(hang/3)*3 + i/3][(lie/3)*3 + i%3] == n)return false;}return true;}bool backtrack(vector<vector<char>>& board, int hang, int lie) {//遍历完这一行最后一列,转而遍历下一行if(lie==9){return backtrack(board, hang+1, 0);}//找到一个解,返回if(hang == 9) return true;// 就是对每个位置进行穷举for (int i = hang; i < 9; i++) {for (int j = lie; j < 9; j++) {// 如果该位置是预设的数字,不用我们操心if (board[i][j] != '.') {return backtrack(board, i, j + 1);} //如果不是预置的数字for (char ch = '1'; ch <= '9'; ch++) {// 如果遇到符合规则的数字,填入if (isValid(board, i, j, ch)){// 做选择board[i][j] = ch;// 继续穷举下一列,如果找到了一个解,立即结束if(backtrack(board, i, j + 1) == true) return true;// 撤销选择board[i][j] = '.';}}// 穷举完 1~9,依然没有找到可行解,此路不通return false;}}return false;}void solveSudoku(vector<vector<char>>& board) {backtrack(board, 0, 0);return;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速完成兼职外包开发任务

做了很多年的开发相关的工作&#xff0c;做过兼职开发&#xff0c;也做过外包一些开发项目。 兼职人员角色时 正是经历这些事情时&#xff0c;每次就要提前很费经的跟公司沟通&#xff0c;让他们把公司内部的svn开发出去&#xff0c;但是就是很难&#xff0c;会涉及到安全各方的…

使用YOLOv5训练NEU-DET数据集

一、下载YOLOv5源码和NEU-DET(钢材表面缺陷)数据集 YOLOv5源码 NEU-DET(钢材表面缺陷)数据集 这里的数据集已经经过处理了&#xff0c;下载即可 若通过其他途径下载的原始数据集标签为xml格式&#xff0c;需要转化为txt格式XML转txt格式脚本 二、数据集准备 NEU-DET(钢材表…

kotlin获取属性_Kotlin程序获取系统MAC地址

kotlin获取属性The task is to get system MAC address. 任务是获取系统MAC地址。 package com.includehelpimport java.net.InetAddressimport java.net.NetworkInterface//Function to get System MACfun getSystemMac(): String? {return try {val OSName System.getProp…

带分页功能的SSH整合,DAO层经典封装

任何一个封装讲究的是&#xff0c;使用&#xff0c;多状态。Action&#xff1a;任何一个Action继承分页有关参数类PageManage&#xff0c;自然考虑的到分页效果&#xff0c;我们必须定义下几个分页的参数。并根据这个参数进行查值。然后在继承ServiceManage&#xff0c;Service…

在windows phone Mango中使用原生代码开发程序

本文不讨论创建可执行的exe程序,主要想说明怎么在silverlight程序里面调用由原生代码所编写的DLL(C / ARM). 原生代码可以调用更多的API,但是这并不是说你就能随意获得那些你没有权限的资源,比如,你可以使用CopyFile这个API,但是如果你试图把文件Copy到\Windows文件夹,就会得到…

leetcode 198. 打家劫舍 思考分析

目录1、题目2、求解思路3、代码1、题目 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动…

找不到Windows照片查看器解决方法

桌面创建一个txt文本 复制这些命令&#xff0c;之后将后缀改为.reg&#xff0c;右击管理员身份运行即可 Windows Registry Editor Version 5.00 ; Change Extensions File Type [HKEY_CURRENT_USER\Software\Classes\.jpg] "PhotoViewer.FileAssoc.Tiff" ; Change E…

数字拆分为斐波那契数列_检查数字是否为斐波那契

数字拆分为斐波那契数列Description: 描述&#xff1a; We are often used to generate Fibonacci numbers. But in this article, we are going to learn about how to search Fibonacci numbers in an array? 我们经常被用来产生斐波那契数。 但是在本文中&#xff0c;我们…

伙伴分配器的一个极简实现

提起buddy system相信很多人不会陌生&#xff0c;它是一种经典的内存分配算法&#xff0c;大名鼎鼎的Linux底层的内存管理用的就是它。这里不探讨内核这么复杂实现&#xff0c;而仅仅是将该算法抽象提取出来&#xff0c;同时给出一份及其简洁的源码实现&#xff0c;以便定制扩展…

[USACO3.2.3 Spinning Wheels]

[关键字]&#xff1a;模拟 枚举 [题目大意]&#xff1a;有5个轮子&#xff0c;每个轮子优r个缺口并且会按一定速度不停转动&#xff0c;问什么时候可以使一条光线射过所有轮子。 // [分析]&#xff1a;从0到1000&#xff08;或其他的&#xff09;枚举分钟然后判断&#xff0c;当…

一、SQLServer2008安装(带密码)、创建数据库、C#窗体项目测试

一、下载和安装SQLServer2008 东西太大了&#xff0c;没法上传到资源里面&#xff0c;官网其他公众号都下载可以。 右击管理员身份 运行setup.exe 这个密钥不能用的话&#xff0c;也可以去百度其他密钥 JD8Y6-HQG69-P9H84-XDTPG-34MBB 建议改一下路径&#xff0c;我这边修…

python获取当前日期_Python程序获取当前日期

python获取当前日期In the below example – we are implementing a python program to get the current date. 在下面的示例中-我们正在实现一个python程序来获取当前日期 。 Steps: 脚步&#xff1a; Import the date class from datetime module. 从datetime模块导入日期类…

【C++grammar】多态、联编、虚函数

目录1、多态概念1.多态性有两种表现的方式2、联编&#xff08;实现多态&#xff09;1.静态联编2.动态联编3、实现运行时多态1.为何要使用运行时多态&#xff1f;2.如何实现运行时多态3.多态的例子1.调用哪个同名虚函数&#xff1f;2. 用途&#xff1a;可以用父类指针访问子类对…

一 MVC - HtmlHelper

HtmlHelper类位于System.Web.Mvc.Html之中主要有七个静态类组成&#xff1a; FormExtensions - BeginForm, BeginRouteForm, EndForm InputExtensions - CheckBox, CheckBoxFor, Hidden, HiddenFor, Password, PasswordFor, RadioButton, RadioButtonFor, TextBox, TextBoxFor …

HDOJ 400题纪念。

刚刚交了1506&#xff0c;无意间瞟到左边的随笔数&#xff0c;发现已经401题了&#xff0c;这么说前几天就400题了啊囧。 昨天还想交到400题就先放放&#xff0c;背单词的&#xff0c;没想到那么快。等把USACO那个八皇后写完吧。人生总是有许多不想做又不得不做的事情。。。 还…

二、用户登录和注册

一、页面设计 一共四个页面 主页面Form1&#xff0c;登录页面login&#xff0c;注册页面resister&#xff0c;主菜单页面main_page 系统运行进入Form1&#xff0c;单击登录按钮跳转到login&#xff0c;数据库中得存在数据信息且输入正确才可登录成功&#xff0c;跳转到main_pa…

readdir函数_PHP readdir()函数与示例

readdir函数PHP readdir()函数 (PHP readdir() function) The full form of readdir is "Read Directory", the function readdir() is used to read the directory i.e. read the name of the next entry in the directory. readdir的完整形式为“ Read Directory”…

【C++grammar】访问控制与抽象类与纯虚函数

目录一、访问控制 (可见性控制)1.private、public、protected关键字2.关键字示例1、关键字对类数据成员访问的限制3. 公有继承4. 私有继承5. 保护继承6. 私有继承和保护继承的区别二、抽象类与纯虚函数1.什么是抽象类2.抽象函数/纯虚函数3.抽象类示例一、访问控制 (可见性控制)…

mongodb 如何删除 字段值为 json对象中的某个字段值

例如&#xff1a; { attributes: { birthday:1988-01-01, name: aq } } birthday是attributes字段的value的一个字段&#xff0c; 我要删除birthday 用这句话&#xff1a; db.User.update({email:adminlinkris.com},{$unset:{attributes.birthday:}})转载于:https://www.cnblog…

使用 Spring 的 Web 服务模拟器框架解决方案

http://www.ibm.com/developerworks/cn/web/wa-aj-simulator/index.html转载于:https://www.cnblogs.com/diyunpeng/archive/2012/02/28/2371390.html