乘风破浪:LeetCode真题_037_Sudoku Solver
乘风破浪:LeetCode真题_037_Sudoku Solver
一、前言
这次我们对于上次的模型做一个扩展并求解。
二、Sudoku Solver
2.1 问题
2.2 分析与解决
这道题让我们按照规则,填写数独表上的内容,并且已知假设答案是唯一的。这里我们直到一个3*3的方格内的数字不能重复,因此须要填写完成,就需要所有的数字,因此我们可以尝试使用图遍历中的深度优先和广度优先遍历来不断地试探,直到得到最后的结果。同样的递归也能达成上面的要求。
class Solution {
int[][] hCounts;
int[][] vCounts;
int[][][] sqCounts;
public void solveSudoku(char[][] board) {
hCounts = new int[9][9];
vCounts = new int[9][9];
sqCounts = new int[3][3][9];
for (int row=0;row<9;row++) {
for (int col=0;col<9;col++)
if (board[row][col] != '.')
set(board, row, col, board[row][col]);
}
solve(board, 0, 0);
}
private boolean solve(char[][] board, int row, int col) {
if (row == board.length)
return true;
if (col == board[0].length)
return solve(board, row+1, 0);
if (board[row][col] != '.')
return solve(board, row, col+1); for (int i=1;i<10;i++) {
char n = (char)('0' + i);
if (canAdd(row, col, n)) {
set(board, row, col, n);
if (solve(board, row, col+1))
return true;
unset(board, row, col, n);
}
}
return false;
}
private boolean canAdd(int row, int col, char c) {
int n = c-'0'-1;
return hCounts[row][n] == 0 && vCounts[col][n] == 0 && sqCounts[row/3][col/3][n] == 0;
}
private void set(char[][] board, int row, int col, char c) {
board[row][col] = c;
int n = c-'0'-1;
hCounts[row][n]++;
vCounts[col][n]++;
sqCounts[row/3][col/3][n]++;
}
private void unset(char[][] board, int row, int col, char c) {
board[row][col] = '.';
int n = c-'0'-1;
hCounts[row][n]--;
vCounts[col][n]--;
sqCounts[row/3][col/3][n]--;
}
}
这道题的算法可以说是非常经典的,进行了一些抽象,首先是初始化,通过三个数组来检验能不能添加元素进去。方法也很简单,如果存在过某个数值,就加一,然后再添加的时候需要判断一下是不是能够加入进去。
private boolean canAdd(int row, int col, char c) {
int n = c-'0'-1;
return hCounts[row][n] == 0 && vCounts[col][n] == 0 && sqCounts[row/3][col/3][n] == 0;
}
private void set(char[][] board, int row, int col, char c) {
board[row][col] = c;
int n = c-'0'-1;
hCounts[row][n]++;
vCounts[col][n]++;
sqCounts[row/3][col/3][n]++;
}
之后我们从最开始的[0,0]按行遍历,通过递归算法,如果能将字符加入进去就加入,继续调用,不能的话就撤回,然后继续遍历,先对每一行的每一列的元素进行遍历,当完成之后遍历下一行,直至结束。
private boolean solve(char[][] board, int row, int col) {
if (row == board.length) //已经遍历到表外了,结束,成功。
return true;
if (col == board[0].length) //开始下一行
return solve(board, row+1, 0);
if (board[row][col] != '.') //不为.则继续下一列。
return solve(board, row, col+1);
for (int i=1;i<10;i++) {
char n = (char)('0' + i);
if (canAdd(row, col, n)) {
set(board, row, col, n);
if (solve(board, row, col+1))
return true;
unset(board, row, col, n);//不成功,回退
}
}
return false; //最后都没成功,返回false
}
三、总结
涉及到图的问题,让我们想到了八皇后问题,同样的联想到这个题的解法。
乘风破浪:LeetCode真题_037_Sudoku Solver的更多相关文章
- 乘风破浪:LeetCode真题_041_First Missing Positive
乘风破浪:LeetCode真题_041_First Missing Positive 一.前言 这次的题目之所以说是难,其实还是在于对于某些空间和时间的限制. 二.First Missing Posi ...
- 乘风破浪:LeetCode真题_040_Combination Sum II
乘风破浪:LeetCode真题_040_Combination Sum II 一.前言 这次和上次的区别是元素不能重复使用了,这也简单,每一次去掉使用过的元素即可. 二.Combination Sum ...
- 乘风破浪:LeetCode真题_039_Combination Sum
乘风破浪:LeetCode真题_039_Combination Sum 一.前言 这一道题又是集合上面的问题,可以重复使用数字,来求得几个数之和等于目标. 二.Combination Sum ...
- 乘风破浪:LeetCode真题_038_Count and Say
乘风破浪:LeetCode真题_038_Count and Say 一.前言 这一道题目,很类似于小学的问题,但是如果硬是要将输入和结果产生数值上的联系就会产生混乱了,因此我们要打破思维定势. ...
- 乘风破浪:LeetCode真题_036_Valid Sudoku
乘风破浪:LeetCode真题_036_Valid Sudoku 一.前言 有的时候对于一些基础知识的掌握,对我们是至关重要的,比如ASCII重要字符的表示,比如一些基本类型的长度. 二.Valid ...
- 乘风破浪:LeetCode真题_035_Search Insert Position
乘风破浪:LeetCode真题_035_Search Insert Position 一.前言 这次的问题比较简单,也没有限制时间复杂度,但是要注意一些细节上的问题. 二.Search Insert ...
- 乘风破浪:LeetCode真题_034_Find First and Last Position of Element in Sorted Array
乘风破浪:LeetCode真题_034_Find First and Last Position of Element in Sorted Array 一.前言 这次我们还是要改造二分搜索,但是想法却 ...
- 乘风破浪:LeetCode真题_033_Search in Rotated Sorted Array
乘风破浪:LeetCode真题_033_Search in Rotated Sorted Array 一.前言 将传统的问题进行一些稍微的变形,这个时候我们可能无所适从了,因此还是实践出真知, ...
- 乘风破浪:LeetCode真题_032_Longest Valid Parentheses
乘风破浪:LeetCode真题_032_Longest Valid Parentheses 一.前言 这也是非常有意思的一个题目,我们之前已经遇到过两个这种括号的题目了,基本上都要用到堆栈来解决,这次 ...
随机推荐
- UVa 10129 Play on Words(并查集+欧拉路径)
题目链接: https://cn.vjudge.net/problem/UVA-10129 Some of the secret doors contain a very interesting wo ...
- dom操作------获取元素的若干方法
// 1,getElementById:返回元素节点document.getElementById(); // 2,getElementsByClassName:返回HTMLCollection对象( ...
- CPU简单科普
CPU简单科普 本文仅限于对小白科普. 误解一:CPU使用率和硬盘使用率一样. 误解二:一台电脑只有一个CPU. 误解三:CPU的核数,就是CPU的数量. 误解三:CPU主频越高越厉害:CPU核数越多 ...
- [原] jQuery EasyUI 1.3.4 离线API、Demo (最新)
说明 本文下载包为 jQuery EasyUI 1.3.4 离线API.Demo. API 按照分类整理做成了离线版本,文档保证和官网完全一致: Demo 按照分类整理为合集. 1.3.3版本中新增 ...
- 任意的组合,数组或数组,数组或list,list或list不用循环得出匹配的总数和需要的字段列
var res = list.Where(p=> list2.Any(x=>x.Id == p.Id));var count = res.Count();var ids = res.Sel ...
- (微信小程序)一 : 初识微信小程序
首先看过angularjs的同学们在看微信小程序的创始文件应该不算很陌生吧. 需要看的 先是文件目录 看完这个目录..得知 ( 一 ) pages 他存放于多个页面 如 index ,log ...
- Nodejs+Express构建网站
1.预先安装(系统环境widows): nodejs 可在官网下载安装 https://nodejs.org/en/ visual studio code 可在官网下载安装 http://co ...
- async和await学习笔记
结论: (1)asyc方法的返回类型必须为:void.Task或者Task<T>.返回类型为Task的异步方法中无需使用return返回值,而返回类型为Task<TResult> ...
- mongdb查询操作
1.db.table.find() 查询所有信息 db.table.findOne()查询第一个信息2.db.table.find({条件},{要显示列}) db.table.find({},{_id ...
- django 参考
1. 路由系统 https://www.cnblogs.com/maple-shaw/articles/9282718.html 2. 视图 https://www.cnblogs.com/maple ...