Leetcode 37. 解数独

1.题目基本信息

1.1.题目描述

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

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

  • 数字 1-9 在每一行只能出现一次。
  • 数字 1-9 在每一列只能出现一次。
  • 数字 1-9 在每一个以粗实线分隔的 3×3 宫内只能出现一次。(请参考示例图)
    数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

1.2.题目地址

https://leetcode.cn/problems/sudoku-solver/description/

2.解题方法

2.1.解题思路

回溯

2.2.解题步骤

第一步,使用数组记录每一行、每一列、每一块的各个数字的存在状态,分别记为rows、cols、blocks,其中rows[i][j]=True表示j+1数字在下标为i的行中,反之亦然,cols和blocks也同理。与此同时,使用spaces记录所有为空的点的坐标,在后续的回溯中将其遍历填充。

第二步,构建回溯函数

  • 函数传入当前处理的空坐标在spaces数组中的下标spaceIndex,返回内容为spaces[spaceIndex:]能否构建完整的合法的数独组合。
  • 回溯本质上还是递归,所以第一步判断边界条件,当spaceIndex=len(spaces)时,根据返回内容的性质,可知返回True;
  • 第二步,遍历1-9,如果当前位置的行、列、块都没有该数字,则可以将该数字填入当前的spaceIndex的位置,同时标记rows、cols、blocks该位置为True,标记完后,递归spaceIndex+1处的下一个空位置,获取spaces[spaceIndex+1:]是否能构建合法的数独,记为valid,然后将rows、cols、blocks回溯为False(回溯是为了不影响后面在spaceIndex状况的for循环),如果递归返回valid为True,则可以直接退出for循环,代表已经构建了合法的数独,直接返回valid即可;如果经过9次的for循环都没有构建合法的数独,代表spaces[spaceIndex:]不能构建合法的数独,返回False。

注意:在递归的过程中,会将board进行修改,最终的回溯退出时,构建的数独为合法数独组合,此时的board即为题解,由于题目已经声明了数独一定有解,所以spaceIndex=0时的回溯函数一定返回True

3.解题代码

Python代码

class Solution:
    # 回溯
    # 第一步,使用数组记录每一行、每一列、每一块的各个数字的存在状态,分别记为rows、cols、blocks,其中rows[i][j]=True表示j+1数字在下标为i的行中,反之亦然,cols和blocks也同理。与此同时,使用spaces记录所有为空的点的坐标,在后续的回溯中将其遍历填充。
    # 第二步,构建回溯函数
    # > 函数传入当前处理的空坐标在spaces数组中的下标spaceIndex,返回内容为spaces[spaceIndex:]能否构建完整的合法的数独组合。
    # > 回溯本质上还是递归,所以第一步判断边界条件,当spaceIndex=len(spaces)时,根据返回内容的性质,可知返回True;
    # > 第二步,遍历1-9,如果当前位置的行、列、块都没有该数字,则可以将该数字填入当前的spaceIndex的位置,同时标记rows、cols、blocks该位置为True,标记完后,递归spaceIndex+1处的下一个空位置,获取spaces[spaceIndex+1:]是否能构建合法的数独,记为valid,然后将rows、cols、blocks回溯为False(回溯是为了不影响后面在spaceIndex状况的for循环),如果递归返回valid为True,则可以直接退出for循环,代表已经构建了合法的数独,直接返回valid即可;如果经过9次的for循环都没有构建合法的数独,代表spaces[spaceIndex:]不能构建合法的数独,返回False。
    # 注意:在递归的过程中,会将board进行修改,最终的回溯退出时,构建的数独为合法数独组合,此时的board即为题解,由于题目已经声明了数独一定有解,所以spaceIndex=0时的回溯函数一定返回True
    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        # 从spaces中第一个位置开始遍历回溯;返回spaces[spaceIndex:]能不能填充成合法的数独,并在判断过程中设置board,在合法的数独填充时退出回溯
        def backtrack(spaceIndex):
            if spaceIndex==len(spaces):
                return True
            valid=False
            for i in range(9):
                row,col=spaces[spaceIndex]
                if not rows[row][i] and not cols[col][i] and not blocks[row//3*3+col//3][i]:
                    board[row][col]=str(i+1)
                    rows[row][i]=cols[col][i]=blocks[row//3*3+col//3][i]=True
                    valid=backtrack(spaceIndex+1)
                    rows[row][i]=cols[col][i]=blocks[row//3*3+col//3][i]=False
                if valid:
                    break
            return valid
        # 第一步,记录当前数独数组的行、列、块的状态;rows[i][j]指下标为i的行的数字j+1是否存在,cols和blocks同理
        rows=[[False]*9 for _ in range(9)]
        cols=[[False]*9 for _ in range(9)]
        blocks=[[False]*9 for _ in range(9)]
        spaces=[]   # 空的位置的坐标列表
        for i in range(9):
            for j in range(9):
                if board[i][j]!=".":
                    num=int(board[i][j])
                    rows[i][num-1]=True
                    cols[j][num-1]=True
                    blocks[i//3*3+j//3][num-1]=True
                else:
                    spaces.append((i,j))
        # print(rows,"\n",cols,"\n",blocks)
        # print(spaces)
        # print(backtrack(0))
        backtrack(0)

C++代码

class Solution {

private:
    vector<vector<bool>> rows;
    vector<vector<bool>> cols;
    vector<vector<bool>> blocks;
    vector<pair<int,int>> spaces;

public:
    bool backtrack(int spaceIndex,vector<vector<char>>& board){
        if(spaceIndex==spaces.size()){
            return true;
        }
        bool valid=false;
        for(int i=0;i<9;++i){
            int row=spaces[spaceIndex].first,col=spaces[spaceIndex].second;
            if(!rows[row][i] && !cols[col][i] && !blocks[row/3*3+col/3][i]){
                board[row][col]=(i+1)+'0';
                rows[row][i]=cols[col][i]=blocks[row/3*3+col/3][i]=true;
                valid=backtrack(spaceIndex+1,board);
                rows[row][i]=cols[col][i]=blocks[row/3*3+col/3][i]=false;
            }
            if(valid)break;
        }
        return valid;
    }
    
    void solveSudoku(vector<vector<char>>& board) {
        rows=vector<vector<bool>>(9,vector<bool>(9,false));
        cols=vector<vector<bool>>(9,vector<bool>(9,false));
        blocks=vector<vector<bool>>(9,vector<bool>(9,false));
        for(int i=0;i<9;++i){
            for(int j=0;j<9;++j){
                if(board[i][j]!='.'){
                    int num=board[i][j]-'0';
                    rows[i][num-1]=true;
                    cols[j][num-1]=true;
                    blocks[i/3*3+j/3][num-1]=true;
                }else{
                    spaces.push_back(pair<int,int>(i,j));
                }
            }
        }
        backtrack(0,board);
    }
};

4.执行结果

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

文件IO及目录操作

一、文件IO 1.1 close函数&#xff08;关闭文件&#xff09; #include <unistd.h>---所需头文件 int close(int fd); 功能&#xff1a;关闭文件 参数&#xff1a;fd&#xff1a;文件描述符 返回值&#xff1a;成功返回0&#xff0c;失败返回-1&#xff0c;置位错误码 …

主机加固的关键要素:服务器防病毒

在数字化浪潮中&#xff0c;网络安全已成为企业不可忽视的一环。尤其是安全运维人员&#xff0c;他们肩负着保护企业数据不受侵害的重任。MCK主机加固解决方案&#xff0c;正是为了应对这一挑战而生。 网络安全的严峻现实 不久前&#xff0c;一家知名企业因勒索病毒攻击而被迫…

二分查找一>0~n-1中缺失的数字(点名)

1.题目&#xff1a; 2.解析&#xff1a;方法一&#xff1a;用哈希表&#xff1a;记录存在的数字&#xff0c;找到哈希表为空的数字输出 Set<Integer> set new HashSet<>();for(int x : records) set.add(x);for(int i 0; i < set.size(); i){if(!set.contain…

Linux系列-Linux的常见指令

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” Linux基本指令 ls指令 语法&#xff1a;ls 【选项】【目录或文件】 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件&#xff0c;对于文件&#xf…

【GO基础学习】环境安装到基础语法(1)

文章目录 环境安装GoLand 安装GO基础GO特点类型和函数Init函数和main函数GO命令下划线变量和常量数组切片Slice 引用 环境安装 下载地址&#xff1a;https://www.golangroadmap.com/ 安装目录文件说明&#xff1a; api&#xff1a;每个版本的 api 变更差异。 bin&#xff1…

基于SpringBoot+Vue的船舶监造系统(带1w+文档)

基于SpringBootVue的船舶监造系统(带1w文档) 基于SpringBootVue的船舶监造系统(带1w文档) 大概在20世纪90年代&#xff0c;我国才开始研发船舶监造系统&#xff0c;与一些发达国家相比&#xff0c;系统研发起步比较晚。当时的计算机技术刚开始发展起来&#xff0c;国家经济力量…

Map的实现类:HashMap

在API获取HsahMap类的全部信息 实例代码&#xff1a;创建一个Student类和Demo02 package com.map;public class Student {private String name;private int stuNo;public Student(String name, int stuNo) {this.name name;this.stuNo stuNo;}public String getName() {retu…

从零开始构建:Python自定义脚本自动化你的日常任务

从零开始构建&#xff1a;Python自定义脚本自动化你的日常任务 Python 作为一种简洁且功能强大的编程语言&#xff0c;被广泛应用于各种自动化任务中。通过编写 Python 脚本&#xff0c;你可以轻松地将日常重复性工作自动化&#xff0c;例如文件操作、数据处理、网络爬虫、系统…

C++ | Leetcode C++题解之第457题环形数组是否存在循环

题目&#xff1a; 题解&#xff1a; class Solution { public:bool circularArrayLoop(vector<int>& nums) {int n nums.size();auto next [&](int cur) {return ((cur nums[cur]) % n n) % n; // 保证返回值在 [0,n) 中};for (int i 0; i < n; i) {if …

STM32 407 RS485通信实现数据收发【我的创作纪念日】

1. 前言 本例中的485驱动&#xff0c;基于标准库编写&#xff0c;不是HAL库&#xff0c;请大家注意。 最近搞嵌入式程序&#xff0c;踩了不少坑&#xff0c;这里统一记录一下。 2. 收获 1.串口通信&#xff0c;数据是一个字节一个字节的发送&#xff0c;对方收到的数据是放在…

github学生认证(Github Copilot)

今天想配置一下Github Copilot&#xff0c;认证学生可以免费使用一年&#xff0c;认证过程中因为各种原因折腾了好久&#xff0c;记录一下解决方法供大家参考。 p.s.本文章只针对Github学生认证部分遇到的问题及解决方法&#xff0c;不包括配置copilot的全部流程~ 1、准备工作…

无图化加速!MemFusionMap提出时序重叠热图策略,在线建图mAP暴涨5.4%!

导读&#xff1a; HDMap对于自动驾驶系统至关重要&#xff0c;因为它可以为规划提供了精细的道路信息。尽管现有的单帧输入方法在在线矢量化高精地图构建方面取得了不错的成绩&#xff0c;但在处理复杂场景和遮挡时仍然存在挑战。为了解决这些问题&#xff0c;作者提出了 MemFu…

AWR1642+DCA1000采集ADC数据并解析

文章同步发布在CSDN和公众号(雷达原理与系统),后续文章中出现的资料,参考文档等都会放在GitHub仓库,欢迎fork和star。 0. 序言 为什么要先将采集ADC数据呢?因为ADC数据是信号处理的输入,是后续理解信号处理手段的基础。当然这里也可以采用仿真信号,但我的想法是单独出…

SQL第13课——创建高级联结

本课讲另外一些联结&#xff08;含义和使用方法&#xff09;&#xff0c;如何使用表别名&#xff0c;如何对被联结的表使用聚集函数。 13.1 使用表别名 第7课中使用别名引用被检索的表列&#xff0c;给列起别名的语法如下&#xff1a; SQL除了可以对列名和计算字段使用别名&a…

聚类分析 | IPOA优化FCM模糊C均值聚类优化算法

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 (多图聚类)IPOA优化FCM模糊C均值聚类优化算法&#xff0c;matlab代码&#xff0c;超多图 基于改进的鹈鹕优化算法&#xff08;IPOA&#xff09;优化FCM模糊C均值聚类优化&#xff0c;matlab代码&#xff0c;直接运行…

HTB:Preignition[WriteUP]

连接至HTB服务器并启动靶机 靶机IP&#xff1a;10.129.157.49 分配IP&#xff1a;10.10.16.12 1.Directory Brute-forcing is a technique used to check a lot of paths on a web server to find hidden pages. Which is another name for this? (i) Local File Inclusion, (…

窗口售票系统1.0版本

本窗口售票系统实现了三个售票窗口的随机售票&#xff0c;实现随机到某一个窗口买票&#xff0c;总票余量都会减少&#xff0c;即三个窗口共享同一个票余量。若票余量小于一次性购票量&#xff0c;则提示报错&#xff1b;若车票售罄&#xff0c;则代码结束运行。 代码实现&…

用户和组管理

用户管理 用户管理包括创建用户、修改用户属性、删除用户等操作。 创建用户 使用 useradd 命令可以创建新用户。 格式&#xff1a;useradd [选项] username 步骤1&#xff1a;创建新用户 useradd tom 步骤 2: 设置用户密码 新用户创建后&#xff0c;需要设置一个密码才能…

需求8——通过一个小需求来体会AI如何帮助改bug

这篇文章&#xff0c;我们通过一个简单的例子来说明&#xff0c;平时在写需求的时候&#xff0c;我们可以在什么时候用AI来帮助我们写代码。 首先来看一下这个需求&#xff1a;系统中某个用户使用的时候出现了bug&#xff0c;通过手机建立临时任务报错&#xff0c;没有办法新增…

ElasticSearch备考 -- Update by query Reindex

一、题目 有个索引task&#xff0c;里面的文档长这样 现在需要添加一个字段all&#xff0c;这个字段的值是以下 a、b、c、d字段的值连在一起 二、思考 需要把四个字段拼接到一起&#xff0c;组成一个新的字段&#xff0c;这个就需要脚本&#xff0c; 这里有两种方案&#xff…