LeetCode算法题解(回溯,难点)|LeetCode37. 解数独

LeetCode37. 解数独

题目链接:37. 解数独
题目描述:

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

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

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

数独部分空格内已填入了数字,空白格用 '.' 表示。

示例 1:

输入:board = [["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]]
输出:[["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","6","1","4","2","3"],["4","2","6","8","5","3","7","9","1"],["7","1","3","9","2","4","8","5","6"],["9","6","1","5","3","7","2","8","4"],["2","8","7","4","1","9","6","3","5"],["3","4","5","2","8","6","1","7","9"]]
解释:输入的数独如上图所示,唯一有效的解决方案如下所示:


提示:

  • board.length == 9
  • board[i].length == 9
  • board[i][j] 是一位数字或者 '.'
  • 题目数据 保证 输入数独仅有一个解

算法分析:

利用回溯法确定并放置每个格子能放值的数字。

回溯的返回值类型为boolean,只要找到一个符合的条件就直接返回true。

利用双重for循环搜索每个格子的位置,并判断该格子是否是空格,如果不是空格不是空格直接跳过这一个格子。

   public boolean backTravel(int x, int y, char[][] board) {
       for(int i = x; i < board.length; i++) {
           for(int j = y; j < board[0].length; j++) {//遍历每一个格子
               if(board[i][j] != '.') continue;
               ....
           }
       }
   }

如果该格子是空格子,判断该格子是否可以放入1-9当中的数字如果可以,放入数字,然后递归、回溯。

for(char ch = '1'; ch <= '9'; ch++) {
   if(canPut(ch, i, j, board)) {//判断当前空白格是否可以用1-9数字来填入
      board[i][j] = ch;//如果可以将数字字符填入空格内
      if(backTravel(i, y, board)) return true;//然后递归,如果递归返回的是true那么说明找到了解决方案,直接返回true
      board[i][j] = '.';//如果没找到,进行回溯
   }
}

判断是否可以放数字的函数:

public boolean canPut(char ch, int x, int y, char[][] board) {//判断当下坐标是否可以放置ch
        for(int i = 0; i < board.length; i++) {//判断这一列是否出现过ch
            ...
        }
        for(int j = 0; j < board[0].length; j++) {//判断这一行是否出现过ch
            ...
        }
        //找到当前格子所属的3*3宫格的左上角坐标
        int startx = (x/3)*3;
        int starty = (y/3)*3;
        for(int i = startx; i < startx + 3; i++) {//判断当前坐标所属的3*3宫格内是否出现ch
            for(int j = starty; j < starty + 3; j++) {
                ...
            }
        }
        return true;
    }

完整的代码如下:

class Solution {
    public boolean canPut(char ch, int x, int y, char[][] board) {//判断当下坐标是否可以放置ch
        for(int i = 0; i < board.length; i++) {//判断这一列是否出现过ch
            if(board[i][y] == ch)
            return false;
        }
        for(int j = 0; j < board[0].length; j++) {//判断这一行是否出现过ch
            if(board[x][j] == ch)
            return false;
        }
        //找到当前格子所属的3*3宫格的左上角坐标
        int startx = (x/3)*3;
        int starty = (y/3)*3;
        for(int i = startx; i < startx + 3; i++) {//判断当前坐标所属的3*3宫格内是否出现ch
            for(int j = starty; j < starty + 3; j++) {
                if(board[i][j] == ch) 
                return false;
            }
        }
        return true;
    }
    public boolean backTravel(int x, int y, char[][] board) {
       for(int i = x; i < board.length; i++) {
           for(int j = y; j < board[0].length; j++) {//遍历每一个格子
               if(board[i][j] != '.') continue;
               for(char ch = '1'; ch <= '9'; ch++) {
                   if(canPut(ch, i, j, board)) {//判断当前空白格是否可以用1-9数字来填入
                       board[i][j] = ch;//如果可以将数字字符填入空格内
                       if(backTravel(i, y, board)) return true;//然后递归,如果递归返回的是true那么说明找到了解决方案,直接返回true
                       board[i][j] = '.';//如果没找到,进行回溯
                   }
               }
               //1-9都不能填入当前空格,说明找不到解诀数独的方法,返回false
               return false;
           }
       }
       //遍历完了都没有返回false,说明找到了合适的棋盘位置,返回true
       return true;
    }
    public void solveSudoku(char[][] board) {
        backTravel(0, 0, board);
    }
}

总结

这道题的难点是对每个空格子该放入哪个数字,以及什么时候结束回溯的操作。

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

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

相关文章

【C++ 学习 ㉟】- 异常详解

目录 一、C 异常处理的基本语法 1.1 - 抛出异常 1.2 - 检测和捕获异常 二、在函数调用链中异常栈展开的匹配原则 三、异常重新抛出 四、异常规范 五、C 标准异常体系 程序的错误大致可以分为以下三种&#xff1a; 语法错误&#xff1a;在编译和链接阶段就能发现&#xf…

<蓝桥杯软件赛>零基础备赛20周--第5周--杂题-2

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周&#xff08;读者可以按…

Java,多线程,线程的两种创建方式

首先是多线程的一些相关概念&#xff1a; 相关概念&#xff1a; 程序&#xff08;program&#xff09;&#xff1a;为完成特定任务&#xff0c;用某种语言编写的一组指令的集合。即指一段静态&#xff08;指不在执行中&#xff09;的代码。 进程&#xff08;process&#xf…

Qt QTableWidget表格的宽度

默认值 QTableWIdget的表格宽度默认是一个给定值&#xff0c;可以手动调整每列的宽度&#xff0c;也不填满父窗口 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {this->resize(800,600);QStringList contents{"11","111111111111",&…

聊聊模板引擎<Template engine>

模板引擎是什么 模板引擎是一种用于生成动态内容的工具&#xff0c;通常用于Web开发中。它能够将静态的模板文件和动态数据结合起来&#xff0c;生成最终的HTML、XML或其他文档类型。模板引擎通过向模板文件中插入变量、条件语句、循环结构等控制语句&#xff0c;从而实现根据…

操作系统:输入输出管理(一)系统概述与设备独立性软件

一战成硕 5.1 I/O系统概述5.1.1 I/O设备5.1.2 I/O控制方式5.1.3 I/O软件层次结构5.1.4 应用程序的I/O接口 5.2 设备独立性软件5.2.1 与设备无关的软件5.2.2 高速缓存与缓冲区5.2.3 设备分配与回收5.2.4 spooling技术&#xff08;假脱机技术&#xff09; 5.1 I/O系统概述 5.1.1…

一分钟秒懂人工智能对齐

文章目录 1.什么是人工智能对齐2.为什么要研究人工智能对齐3.人工智能对齐的常见方法 1.什么是人工智能对齐 人工智能对齐&#xff08;AI Alignment&#xff09;指让人工智能的行为符合人的意图和价值观。 人工智能系统可能会出现“不对齐”&#xff08;misalign&#xff09;…

【EI会议征稿】JPCS独立出版-第五届新材料与清洁能源国际学术会议(ICAMCE 2024)

JPCS独立出版-第五届新材料与清洁能源国际学术会议&#xff08;ICAMCE 2024&#xff09; 2024 5th International Conference on Advanced Material and Clean Energy 第五届新材料与清洁能源国际学术会议&#xff08;ICAMCE 2024&#xff09;将于2024年2月23-25日在中国▪长沙…

电机应用-无刷直流电机

无刷直流电机 无刷直流电机&#xff08;Brushless Dirent Current Motor&#xff0c;简称BLDCM&#xff09;由电动机主体和驱动器组成&#xff0c;无电刷和无换向器&#xff0c;是除了有刷电机外用得最多的一种电机。 无刷直流电机不使用机械的电刷装置&#xff0c;采用方波自控…

带你一分钟看懂 “kubernetes”

目录 什么是 Kubernetes Kubernetes 概述 为什么需要 Kubernetes&#xff0c;它能做什么&#xff1f; 什么是 Kubernetes 从官方网站上可以看到&#xff0c;它是一个工业级的容器编排平台。Kubernetes 这个单词是希腊语&#xff0c;它的中文翻译是“舵手”或者“飞行员”。在…

NFT Insider112:Gucci Cosmos LAND亮相 The Sandbox,和YGG一起探索Web3增长新方式

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members(https://twitter.com/WHALEMembers)、BeepCrypto&#xff08;https://twitter.com/beep_crypto&#xff09;联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周…

0基础制作产品图册的干货,一个网站即可

很多朋友想要制作产品图册&#xff0c;但是不知道如何入手&#xff0c;其实制作产品图册并不难&#xff0c;一个网站就可以搞定。下面就为大家分享一些干货&#xff0c;帮助大家快速入门。 首先&#xff0c;我们需要选择一个合适的网站。比如FLBOOK在线制作电子杂志平台。这个网…

【chat】3: ubutnu 安装mysql-8

如何在 Ubuntu 20.04 上安装 MySQLC搭建集群聊天室&#xff08;七&#xff09;&#xff1a;MySQL数据库配置 及项目工程目录配置 大神是centos的. apt 安装 rootk8s-master-2K4G:~# sudo apt install mysql-server Reading package lists... Done Building dependency tree Re…

SQL触发器

触发器是与表有关的数据库对象。 在insert/update/delete之前(BEFORE)或之后(AFTER)&#xff0c;触发并执行触发 器中定义的SQL语句集合。 触发器的这种特性可以协助应用在数据库端确保数据的完整性, 日志记录 , 数据校验等操作 。 使用别名OLD和NEW来引用触发器中发生变化的…

Google play提高上包率——如何防止封号、拒审、下架?

Google Play是全球最大的移动应用商店之一&#xff0c;它是运行Android操作系统的设备的官方应用商店。它提供各种数字内容&#xff0c;包括应用程序&#xff08;应用&#xff09;、游戏、音乐、书籍等&#xff0c;包括免费和付费选项。这也为许多游戏/APP出海的企业或开发者提…

国内首批!华为云云原生中间件DCSDMS获软件可信“卓越级”认证

11月6日&#xff0c;在软件供应链可信研讨大会上&#xff0c;工业和信息化部电子第五研究所&#xff08;以下简称“电子五所”&#xff09;发布了首批软件产品可信评估结果&#xff0c;并为通过评估的企业颁发证书。 华为云作为中国领先的综合云计算服务商受邀参加本次大会&…

【星海随笔】git的使用

1.在终端&#xff0c;检查git是否安装 git --version 2.没有安装的话去&#xff0c;官网&#xff0c;下载git 3.一直点下一步即可 4.安装后在终端检查git是否安装好 5.设置用户名和邮件地址(最好和GitHub的用户名/邮箱保持一致) git config --global user.name “自己的用户名”…

建表时如何合理选择字段类型

前言 我们在建表的时候关于字段类型的选择会有这么几类人&#xff1a; 严谨型 严格调研每个字段可能的大小&#xff0c;然后根据不同字段类型的限制&#xff0c;进行选择&#xff0c;这一类人在创建关系型数据表的时候是没有问题的。图自己省事型 把所有字段都设置为String&a…

100 寻找重复数

寻找重复数 题解1 二分法题解2 快慢指针(同环形链表2(ab)(ab)kL) 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返…

使用Pytorch的一些小细节(一)

文章目录 前言数据结构-张量max函数索引函数赋值函数拼接函数 前言 由于不经常动手写代码&#xff0c;所以对于python语言中的常见数据结构的用法也不是很熟悉&#xff0c;对于pytorch中的数据结构就更加不熟悉了。之前的代码基础是基于C语言的&#xff0c;属性都是自己定义&a…