【LeetCode】解数独 [H](深度优先遍历)

news2025/1/12 1:53:22

37. 解数独 - 力扣(LeetCode)

一、题目

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

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

  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] 是一位数字或者 '.'
  • 题目数据 保证 输入数独仅有一个解

二、代码

class Solution {
    public void solveSudoku(char[][] board) {
        // row[x][y]:y这个数在第x行是否出现过
        boolean[][] row = new boolean[9][10];
        // col[x][y]:y这个数在第x列是否出现过
        boolean[][] col = new boolean[9][10];
        // bucket[x][y]:y这个数在第x号宫格内是否出现过
        boolean[][] bucket = new boolean[9][10];
        // 初始化上面的三个数组
        initMaps(board, row, col, bucket);

        // 开始暴力递归尝试所有答案,只要找到了一种答案就返回
        process(board, 0, 0, row, col, bucket);
    }

    // 初始化三个辅助数组
    public void initMaps(char[][] board, boolean[][] row, boolean[][] col, boolean[][] bucket) {
        // 开始遍历数独表,构造辅助数组
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (board[i][j] != '.') {
                    int num = board[i][j] - '0';
                    int bid = (i / 3) * 3 + (j / 3);
                    // 标记该数出现在的位置
                    row[i][num] = true;
                    col[j][num] = true;
                    bucket[bid][num] = true;
                }
            }
        }
    }

    // DFS
    // 当前来到(i,j)这个位置,
    // 如果已经有数字,跳到下一个位置上
	// 如果没有数字,尝试1~9,不能和row、col、bucket冲突
    public boolean process(char[][] board, int i, int j, boolean[][] row, boolean[][] col, boolean[][] bucket) {
        // 如果行数已经越界,说明已经尝试完了所有位置,返回true
        if (i > 8) {
            return true;
        }

        // 当离开(i,j),应该去哪?(nexti, nextj)
        // 要通过j是否走到结尾了来决定是不是i要向下走一行,j是否要重新回到0
        int nexti = j < 8 ? i : i + 1;
        int nextj = j < 8 ? j + 1 : 0;
        // 如果当前位置不是空,就继续尝试下一个位置
        if (board[i][j] != '.') {
            return process(board, nexti, nextj, row, col, bucket);
        // 当前位置是空,我们来尝试1~9
        } else {
            // 计算当前数字所在的3*3宫格的编号
            int bid = (i / 3) * 3 + (j / 3);
            // 在该位置尝试填写1~9,看能不能符合要求
            for (int num = 1; num <= 9; num++) {
                // 如果尝试的数字在该行、列、宫格内从未出现,说明符合要求
                if (!row[i][num] && !col[j][num] && !bucket[bid][num]) {
                    // 可以尝试num
                    row[i][num] = true;
                    col[j][num] = true;
                    bucket[bid][num] = true;
                    // 将num填到board中
                    board[i][j] = (char)(num + '0');

                    // 继续递归尝试下一个位置,如果后面都是成立的,就说明找到了一种解法,直接返回true。不再执行后续的尝试,因为题目保证了输入数独仅有一个解
                    if (process(board, nexti, nextj, row, col, bucket)) {
                        return true;
                    }

                    // 恢复现场
                    row[i][num] = false;
                    col[j][num] = false;
                    bucket[bid][num] = false;
                    board[i][j] = '.';
                }
            }
        }
        
        // 如果尝试完了1~9也没有返回true,说明没有符合条件的解,直接返回false
        return false;
    }
}

三、解题思路 

一个一个位置玩DFS暴力尝试。将所有可能填入的数字都尝试一边,找到符合条件的答案就返回。题目保证每一个输入只有唯一的一个解。

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

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

相关文章

设计模式-责任链模式

一、知其然 责任链字面含义第一联想到的就是他是一个链式的行为&#xff0c;就像一个链条一样把所产生的动力传输到到齿轮上一样&#xff1b;还有类似生活中的一个游戏“击鼓传花”&#xff0c;这样说好像也是泛泛而谈&#xff0c;来看看度娘的官方概念&#xff08;摘自百度百科…

[每周一更]-(第26期):反爬虫机制

随着网站的越来越普及&#xff0c;我们开发出来的知识类网站更不希望被竞争对手爬虫&#xff0c;虽然现在网络中充斥着各种各样的蜘蛛&#xff0c;有合法的浏览器爬虫&#xff0c;以及不合法 的人为爬虫&#xff0c;所以攻防战一直都存在&#xff0c;我们只能更好的设定规则&am…

中文文本分类

手把手带你做一个文本分类实战项目(模型代码解读) https://www.bilibili.com/video/BV15Z4y1S7aR/?spm_id_from333.788.recommend_more_video.-1&vd_sourcec47fbb8166930edc486d8fdc405bf569 中文汉字对应的数字索引 之后对应的数字索引 之后找到tokn embedding的东西 1…

34. 池化层 / 汇聚层

1. 池化层 如果我们拍摄黑白之间轮廓清晰的图像X&#xff0c;并将整个图像向右移动一个像素&#xff0c;即Z[i, j] X[i, j 1]&#xff0c;则新图像Z的输出可能大不相同。而在现实中&#xff0c;随着拍摄角度的移动&#xff0c;任何物体几乎不可能发生在同一像素上。即使用三脚…

15【SpringMVC的注解开发】

文章目录二、SpringMVC注解支持2.1 回顾Servlet容器启动源码流程2.2 分析SpringMVC启动源码分析2.2.1 SpringServletContainerInitializer源码分析2.2.2 WebApplicationInitializer源码分析1&#xff09;AbstractContextLoaderInitializer2&#xff09;AbstractDispatcherServl…

短视频播放量超10w后,流量变少的问题解决方案

短视频播放量超10w后&#xff0c;流量变少的问题解决方案 上一篇我们聊了视频播放超10w后&#xff0c;会遇到流量变少的问题并分析了可能的原因&#xff0c;既然知道了原因&#xff0c;那么我们就可以针对性的去解决了。 今天给大家聊一聊在我赢助手跟超200名短视频创作者沟通…

Allegro如何设置差分动态等长规则操作指导

Allegro如何设置差分动态等长规则操作指导 Allegro上可以对差分设置动态等长规则,让差分对在任意一段距离上都是满足等长误差的,尤其是在差分对走线较长的情况下 以下面这两对线为例 具体操作如下 打开constraint Manage选择Physical规则

Linux 管理联网 设置主机名( nmtui图形化 和 hostnamectl命令 )

设置主机名 # 常用的有两种方式&#xff0c;一种是 nmtui 图形化界面的方式来设置&#xff0c; 一种是 hostnamectl 命令的方式来设置。 nmtui 直接在命令行 输入 nmtui 便进入 图形化界面 >>> 最后一选项&#xff08; 红底&#xff09; 便是 设置主机名~&#x…

微导纳米科创板上市:市值125亿 无锡首富王燕清再敲钟

雷递网 雷建平 12月23日江苏微导纳米科技股份有限公司&#xff08;简称&#xff1a;“微导纳米”&#xff0c;股票代码为&#xff1a;“688147”&#xff09;今日在科创板上市。微导纳米此次发行4544.55万股&#xff0c;发行价为24.21元&#xff0c;募资总额为11亿元。微导纳米…

react笔记_11 redux

目录redux定义使用时机redux基本概念StoreStateActionreducerredux工作原理语法[1] 创建StorecreateStorecombineReducers[2]创建并分发actiondispatchapplyMiddleware语法举例说明- 做一个加法运算执行原理redux-thunk中间件使用[3]创建reducer语法渲染过程[4]getState[5]subs…

基于meanshift算法的目标聚类和目标跟踪matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 meanshift算法其实通过名字就可以看到该算法的核心&#xff0c;mean&#xff08;均值&#xff09;&#xff0c;shift&#xff08;偏移&#xff09;&#xff0c;简单的说&#xff0c;也就是有一个…

Web前端105天-day63-HTML5_CORE

HTML5CORE03 目录 前言 一、复习 二、SVG 三、Echarts 四、Webworker 五、回调地狱 六、Promise 七、promiseajax 八、promise_axios 九、async_await 总结 前言 HTML5CORE03学习开始 一、复习 跨域 浏览器的同源策略限定: 网页中利用 AJAX 请求数据, 必须访问同源…

【CSS】flex布局用法解析,快速上手flex布局,flex:1是什么意思?肯定看的懂好吧?

一、flex布局 flex 是 flexible box 的缩写&#xff0c;意为"弹性布局"&#xff0c;用来为盒状模型提供最大的灵活性。 任何一个容器都可以指定为 flex 布局。 采用 flex 布局的元素&#xff0c;称为 flex 容器&#xff08;flex container&#xff09;&#xff0c;…

如何解决跨越

解决跨域我想在坐的各位都会听说过几个解决跨域的方法&#xff1a; 1.有什么 cors后端配置&#xff08;加几个请求头 2.jsonp&#xff08;利用script的src属性&#xff09; 3.还有vue-cli前端配置。 跨域其实就是违背了浏览器的一种策略&#xff0c;这种策略就是同源策略&…

公司刚来的阿里p8,看完我构建的springboot框架,甩给我一份文档

前言&#xff1a; 我们刚开始学习 JavaWeb 的时候&#xff0c;使用 Servlet/JSP 做开发&#xff0c;一个接口搞一个 Servlet &#xff0c;很头大&#xff0c;后来我们通过隐藏域或者反射等方式&#xff0c;可以减少 Servlet 的创建&#xff0c;但是依然不方便&#xff0c;再后…

【Transformer】医学分割领域的应用与扩展(论文阅读)(二) || DETR

声明:仅学习使用~ 目录 1. Transformer学习2. DETR1. Transformer学习 前篇指路:【Transformer】医学分隔领域的应用与扩展(论文阅读)(一) 继续… 关于Self-Attention的公式: 原来是 m x m 是2D的,现在变成1 x m了,是1D的了。 下图中。左图是传统的Transformer,右…

【python圣诞树的实现】

&#x1f935;‍♂️ 个人主页老虎也淘气 个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f44d;&#x1f3fb; 收藏…

拒不外传,阿里内部耗重金找人总结出这份并发编程手册(全彩版)

并发世界很有趣&#xff0c;不要错过 前言&#xff1a; 时间飞逝&#xff0c;转眼间毕业七年多&#xff0c;从事 Java 开发也六年了。我在想&#xff0c;也是时候将自己的 Java 整理成一套体系。 这一次的知识体系面试题涉及到 Java 知识部分、性能优化、微服务、并发编程、开…

python常用模块

time模块 常用操作 1.直接获取时间 time.time() #获取结果是秒数&#xff0c;即从1970年1月1日8:00起计#1671856010.9592516 2.获取结构化时间 time.localtime() #获取本地时间&#xff0c;中国为东八区&#xff0c;为上海时间 time.gmtime() …

C++控制台圣诞树

前言 有是一年圣诞节&#xff0c;先祝大家圣诞节快乐&#xff0c;所以本蒟蒻在AFO之后决定回来更新一篇打印字符圣诞树的教程 &#xff08;呃好吧我承认我就是想嫖奖品&#xff09; 效果展示 呃我知道这有点拉&#xff0c;但是……蒟蒻能有什么坏心思呢&#xff0c;他只不过想…