Sudoku Solver 破解数独 @LeetCode 附DFS感想

Git:不同仓库之间的cherry-pick 【代码】Git:不同仓库之间的cherry-pick。 阅读详情

典型DFS/递归/回溯/深搜题。对于DFS,说白了

1) 什么时候返回?在本题中,1.当x>8或y>8 表示已经遍历完所有的格子,因此成功完成,返回true。2.当下一个搜索(子搜索)返回true,说明已经找到,返回true。  3.如果测试过本轮的所有可能解,但无一是对的,说明无解,返回false。  4.如果当前空格不是空格,则改变x,y坐标后,继续下一个空格的尝试

2)DFS就是针对本轮的所有可能解进行逐一尝试,找到本轮的一个可能解后,这时要调用递归,基于本轮的解对下一轮(子问题)进行求解。如果下一轮(子问题)求解成功,则说明大功告成,及时返回true,停止之后的尝试。

否则如果下一轮(子问题)求解失败,则说明本轮的解不适合子问题,因此,必须换一个本轮的解,然后基于本轮的新解,继续尝试子问题。如果已经本轮所有的解都尝试过了,也都失败了,说明本问题无解,返回false。

当然在每次尝试子问题前和如果失败返回后,都要恢复原来的环境(撤销动作)。

所以,要想使DFS成功返回,条件就是找到满足本轮的解和这个解也要满足下一轮(子问题)。


另外:

1 每个backtracking的题目,最好都有独立判断isValid的程序,这样架构清楚。同时,valid判断函数在这里可以稍微研究一下。只要当前要判断的位置上的数值和本行没有重复,本列没有重复,九宫格没有重复就可以。一旦重复立即返回,减少判断次数。

2 backtracking的递归函数,怎么能没有返回值呢?!因为要判断递归的方案正确与否,所以这里的递归一定是有返回值的(除非是combination那种没有正确错误概念的backtracking)!

3 可以考虑“先放置,再判断”的方案。比如这里,首先判断当前位置是否为空,如果为空,那么放置一个元素,检查它是否正确。如果正确,就继续进行下面的递归(也就是第29行 isValid&&solveSudoku的作用)。当函数返回错误之后,将刚刚的数值变为空,再进行下一次尝试即可。

4 所有的方案(k从1到9)完毕之后,应该返回错误,这个是不应该被忽略的。

http://blog.youkuaiyun.com/zxzxy1988/article/details/8586289

.


package Level4;

/**
 * Sudoku Solver
 * 
 * Write a program to solve a Sudoku puzzle by filling the empty cells.
 * 
 * Empty cells are indicated by the character '.'.
 * 
 * You may assume that there will be only one unique solution.
 * 
 */
public class S37 {

	public static void main(String[] args) {
		char[][] board = {
				{'.','.','9','7','4','8','.','.','.'},
				{'7','.','.','.','.','.','.','.','.'},
				{'.','2','.','1','.','9','.','.','.'},
				{'.','.','7','.','.','.','2','4','.'},
				{'.','6','4','.','1','.','5','9','.'},
				{'.','9','8','.','.','.','3','.','.'},
				{'.','.','.','8','.','3','.','2','.'},
				{'.','.','.','.','.','.','.','.','6'},
				{'.','.','.','2','7','5','9','.','.'},
		};
		solveSudoku(board);
		for(int i=0; i<9; i++){
			for(int j=0; j<9; j++){
				System.out.print(board[i][j]);
			}
			System.out.println();
		}
	}
	
	public static void solveSudoku(char[][] board) {
		dfs(board, 0, 0);
    }

	public static boolean dfs(char[][] board, int x, int y) {
		if(x>8 || y>8){		// 全部深搜完毕
			return true;
		}
		if (board[x][y] == '.') {		// 如果当前是空格
			for (int k = 1; k <= 9; k++) {
				if (isValid(board, x, y, (char) ('0' + k))) {		// 说明在当前空格找到一个满足条件的数字
					board[x][y] = (char) ('0' + k);
					int nextX = x;
					int nextY = y+1;
					if(nextY == 9){
						nextY = 0;
						nextX++;
					}
					if(dfs(board, nextX, nextY)){		// 对下一个空格搜索数字,如果下一个位置找到满足条件的数字,就此返回。否则改变当前空格的数字继续测试
						return true;
					}
					board[x][y] = '.';
				}
			}
			return false;			// 对于当前空格,如果所有的数字都不满足,则无解!
		} else{			// 如果当前已经有数字,就跳过继续深搜
			int nextX = x;
			int nextY = y+1;
			if(nextY == 9){
				nextY = 0;
				nextX++;
			}
			return dfs(board, nextX, nextY);
		}
		
	}

	public static boolean isValid(char[][] board, int x, int y, char k) {
		for(int i=0; i<9; i++){			// 同列检查
			if(board[i][y] == k){
				return false;
			}
			if(board[x][i] == k){			// 同行检查
				return false;
			}
		}
		
		for(int i=0; i<3; i++){			// 九宫格检查
			for(int j=0; j<3; j++){
				if(board[3*(x/3)+i][3*(y/3)+j] == k){
					return false;
				}
			}
		}
		return true;
	}

}

循环处理子问题:

对于每个格子,带入不同的9个数,然后判合法,如果成立就递归继续,结束后把数字设回空。

public class Solution {
    public void solveSudoku(char[][] board) {
        rec(board, 0, 0);
    }
    
    public boolean rec(char[][] board, int x, int y) {
        if(x > 8) {
            return true;
        }
        if(y > 8) {
            return rec(board, x+1, 0);
        }
        
        if(board[x][y] == '.') {
            for(int i=1; i<=9; i++) {
                board[x][y] = (char)('0' + i);      // after setting
                if(isValid(board, x, y)) {          // make sure board is valid
                    if(rec(board, x, y+1)) {        // if we find a solution, return true
                        return true;
                    }
                }
                board[x][y] = '.';
            }
            return false;   // we have tried all possibilities
        } else {
            return rec(board, x, y+1);
        }
    }
    
    public boolean isValid(char[][] board, int x, int y) {
        for(int i=0; i<9; i++) {
            if(i != x && board[i][y] == board[x][y]) {
                return false;
            }
        }
        for(int j=0; j<9; j++) {
            if(j != y && board[x][j] == board[x][y]) {
                return false;
            }
        }
        for(int i=x/3*3; i<x/3*3+3; i++) {      // find which block first, then find that row
            for(int j=y/3*3; j<y/3*3+3; j++) {
                if((i != x || j != y) && board[i][j] == board[x][y]) {
                    return false;
                }
            }
        }
        return true;
    }
}

http://blog.youkuaiyun.com/linhuanmars/article/details/20748761






git cherry-pick的使用        最近在开发一个紧急项目的时候,同事遇到一个很尴尬的问题:一些很重要的代码提交到不是项目的分支上,由于代码数量比较多,所以想通过复制文件重新提交到这个项目分支上有点麻烦。他问我,第一时间没想到git cherry-up命令。在网上搜索后,发现git cherry-up命令真香!解决了同事的问题。        git cherry-pick命令的作用,就是将 阅读详情

相关推荐

centos7安装db2 version11.1

centos7安装db2 version11.1

AKA石头 1061

git cherry-pick命令用法详解

git cherry-pick命令用法详解

IT之一小佬的博客 5万+

如何读懂CiteSpace图谱?科研小白必看的节点颜色/年轮/聚类解读手册

本文详细解析CiteSpace图谱的核心视觉元素,包括节点颜色、年轮和聚类标识,帮助科研人员准确解读数据分析结果。通过生物医学案例展示如何从图谱中识别关键文献和研究趋势,提供五步系统解读法和常见错误规避策略,助力科研小白快速掌握文献计量分析技巧。

weixin_29179311的博客 314

git cherry-pick 的作用与使用方法

cherry-pick ,精心挑选的意思,挑选一个我们需要的 commit 。 其作用:将在其他分支上的 commit 修改,移植到当前的分支。

Eliaukoyx 4831

基于STM32的Keil5代码自动补全设置操作指南

掌握Keil5代码自动补全设置技巧,提升STM32开发效率。通过合理配置编辑器选项,实现智能提示与语法补全,让嵌入式编程更流畅,尤其适合使用keil5代码自动补全设置的开发者快速上手。

weixin_32287387的博客 762

一文掌握python图形界面开发PyQt6--(一)基本操作、控件、信号与槽、常用控件、布局管理、事件处理、文件对话框

一文掌握python图形界面开发PyQt6--(一)基本操作、控件、信号与槽、常用控件、布局管理、事件处理、文件对话框

qq_38120851的博客 4042

Cherry-pick 工具

,

Alex 841

智慧城市中的CV:交通流量监控与行人检测

智慧城市中的CV:交通流量监控与行人检测 ,人工智能,计算机视觉,大模型,AI,计算机视觉作为人工智能的重要分支,通过分析和理解图像或视频数据,为智慧城市提供了强大的感知能力。在交通管理领域,计算机视觉技术可实现交通流量监控、行人检测、违章行为识别等功能,助力构建高效、安全、绿色的城市交通系统。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 5万+

Sudoku python

软件工程基础-个人项目-sudoku游戏] cnblob项目地址 https://github.com/dinodeahonf/Sudoku 解题思路 其目标是用数字填充9×9网格,以便组成网格的9个3×3子网格(也称为“盒”,“块”或“区域”)中的每列,每行和每一个包含所有的数字从1到9.这个益智设置器提供了一个部分完成的网格,这对于一个良好的拼图有一个...

weixin_34268610的博客 300

[DDR5] 模式寄存器 Mode Register MRR/MRW

模式寄存器用于定义各种操作模式。在初始化过程中,可以通过重新执行MRS命令来更改模式寄存器的内容。

串起点滴 1637

“华为杯”研究生数学建模竞赛2019年-【华为杯】D题:汽车行驶工况构建(附获奖论文和MATLAB代码实现)

映了汽车道路行驶的运动学特征。准差、加速度标准差这九个特征参数用于后续的数据分析,建立了合理的汽车运动特征评。特征参数与所属类特征参数的特征值的相关性大小替代误差进行排序的,计算得到汽车行。对于问题一,我们首先对原始数据进行了时间变量转换,将原本的年月日时分秒的计。紧接着进行了运动学片段的划分,引入九个特征参数,通过主成分分析、本文研究的是汽车行驶工况构建,汽车行驶工况是描述汽车行驶的速度。的合理性评价标准,对两种方法都进行了合理性评价,得到的。进行了合理性评价,得到了最优的汽车行驶工况曲线。

getusushu的博客 1000

git cherry-pick使用教程

git cherry-pick 是用来从一个分支中选择一个或多个特定的提交,并将这些提交应用到当前分支。这样可以只选择需要的更改,而不是合并整个分支。

weixin_44977732的博客 5583

【花雕学编程】Arduino ESP32 SPP 之使用Servo库控制360度舵机正反转

使用 Servo 库控制 360 度舵机的正反转是 Arduino ESP32 SPP 应用中的一个重要案例,具有简易控制接口、灵活速度调节和高兼容性等特点,广泛应用于机器人、自动化装置和动态艺术等领域。在第三个案例中,使用map()函数将用户输入的速度参数(范围0-100)映射到舵机控制的角度(0-180),使得用户能够以更人性化的方式控制舵机速度。5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。

雕爷学编程 1468

git cherry-pick使用(git的代码恢复)

这就是使用git cherry-pick恢复代码的过程。把原来老的commit摘到新的分支上面去,然后合并回主干,从而恢复代码。

fxtxz2的专栏 543

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Git Cherry Pick详解

Git是一款分布式版本控制系统,它提供了许多强大的功能来管理代码的版本和变更。其中之一就是命令,它允许我们选择某个分支上的一个或多个提交,并将它们应用到当前分支上。这个功能非常有用,可以帮助我们在不合并整个分支的情况下,将特定的提交应用到其他分支上。本篇博客将详细介绍命令的使用方法和示例。本篇博客详细介绍了命令的使用方法和示例。通过命令,我们可以选择性地将特定的提交应用到其他分支上,而不需要合并整个分支。这对于合并单个提交、修复bug和提取特定功能非常有用。

果酱 の 博客 6万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

git cherry-pick

如果遇到,那么这时就不能直接 merge 或 push。这时可以使用 git cherry-pick来选择性地将某些提交(commit)应用到 devops 分支。

快速成长 485

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Git中的cherry-pick命令是什么,如何使用?

是一个非常强大的命令,可以帮助你灵活地管理提交,特别是在需要从一个分支中选择特定更改时。通过合理使用,你可以更高效地进行代码管理和协作。以下是一些常用的切换到目标分支应用单个提交应用多个提交解决冲突放弃当前的回退到最后一个成功的提交希望这些信息对你有所帮助!

qq_33240556的博客 1873

git cherry-pick详解

对于多分支的代码库,将代码从一个分支转移到另一个分支是常见需求。 这时分两种情况。一种情况是,你需要另一个分支的所有代码变动,那么就采用合并(git merge)。另一种情况是,你只需要部分代码变动(某几个提交),这时可以采用 Cherry pick。 一、基本用法 git cherry-pick命令的作用,就是将指定的提交(commit)应用于其他分支。 $ git cherry-pick <commitHash> 上面命令就会将指定的提交commitHash,应用于当

绝圣弃智-零的博客 1万+

git cherry pick常用用法

是一个强大的 Git 命令,它允许你从一个分支中选择一个或多个提交,并将它们应用到另一个分支上。这在需要将某个分支上的特定提交应用到另一个分支时非常有用,而不必合并整个分支。以下是如果你想从分支中挑选一个特定的提交(比如),并将其应用到master如果你想挑选一系列连续的提交,你可以使用提交范围。例如,挑选从commit1到commit3如果你想挑选多个非连续的提交,你可以多次使用如果你想更详细地选择要挑选的提交,你可以使用或-i如果在挑选提交时出现冲突,Git 会停止并让你解决冲突。

weixin_47582800的博客 1064

(三)分支与标签 - git cherry-pick 命令的使用

核心思想的作用是“采摘”一个或多个已有的提交,并将这些提交的更改作为一个新的提交应用到当前分支上。形象比喻:想象你的 Git 提交历史是一棵樱桃树,每个提交都是一颗樱桃。允许你从树的任意枝干(分支)上,精准地摘下一颗或几颗樱桃(提交),然后嫁接到你当前的枝干(分支)上。与merge和rebasemerge:将整个分支的所有更改整合到另一个分支,会产生一个合并提交。rebase:将一个分支的所有提交“重新播放”到另一个分支的末端,从而形成线性的历史。选择性地应用某些提交,而不是整个分支。

xiaohaha123258的博客 1513

【开源】完美破解九宫格(数独)游戏

数独是一种比较费时费脑的游戏,一般难度的数独玩下来也得1个小时左右,本人是伪数独爱好者,碰到难点的数独需要花上若干个小时,于是偷懒写了一套破解程序,特拿出来分享,希望有人喜欢。 思路: 1、从第一个空格开始,计算出所有可能填充的数字,拿出第一个进行填充,将剩下的可能数字记录下来; 2、接着计算下一个空格所有可能的数字(在前边填充上的基础上),拿出第一个可能进行填充,将剩下的记录; 3、...

844604778 779

git操作之cherry-pick

git操作之cherry-pick

TheOne0226的博客 2万+

git高级特性之 - cherry-pick

详细介绍git cherry-pick的使用,附实用案例说明。

拾年一剑 的专栏 9977

leetcode37 --- solveSudoku(解数独)

1 题目 编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字1-9在每一行只能出现一次。 数字1-9在每一列只能出现一次。 数字1-9在每一个以粗实线分隔的3x3宫内只能出现一次。(请参考示例图) 数独部分空格内已填入了数字,空白格用'.'表示。 2 解法 起始是9*9的格子, 大部分的格子的值是没有确定的, 所以把所有的未确定值的格子放到一个数组里面, 具体可见代码: ...

Michael__Wu的博客 338

git cherry-pick的使用教程

对于多分支的代码库,将代码从一个分支转移到另一个分支是常见需求。 这时分两种情况。一种情况是,你需要另一个分支的所有代码变动,那么就采用合并(git merge)。另一种情况是,你只需要部分代码变动(某几个提交),这时可以采用 Cherry pick。 一、基本用法 git cherry-pick命令的作用,就是将指定的提交(commit)应用于其他分支。 $ git cherry-pick <commitHash> 上面命令就会将指定的提交commitHash,应用于当

前进者 13万+
上一篇: M,BB面试+职业求教
下一篇: Simplify Path 简化文件路径@LeetCode
chiiis
博客等级 码龄14年 422粉丝 429原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值