乘风破浪: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 一.前言 这也是非常有意思的一个题目,我们之前已经遇到过两个这种括号的题目了,基本上都要用到堆栈来解决,这次 ...
随机推荐
- spinnaker自动发布k8s部署应用<一>
一.准备环境 !docker-ce---17.06.2-ce !k8s集群----1.11.1 !helm部署工具---helm-v2.10.0 !spinnaker-charts---spinnak ...
- elasticSearch6源码分析(11)client
1.RestClient /** * Client that connects to an Elasticsearch cluster through HTTP. * <p> * Must ...
- AD分类论文研读(1)
转移性学习对阿尔茨海默病分类的研究 原文链接 摘要 将cv用于研究需要大量的训练图片,同时需要对深层网络的体系结构进行仔细优化.该研究尝试用转移学习来解决这些问题,使用从大基准数据集组成的自然图像得到 ...
- android开发学习笔记系列(6)--代码规范
在开发android的时候,我对自己写的代码很是不满,原因在于自己看到别人的代码,很是头痛,原因很简单,别人写的代码,我就要去猜他的意思,极其烦恼,嗯,就是他没有遵循代码规范,因此我在博客园上寻找一篇 ...
- 表格列mouse经过时高亮显示
前几天Insus.NET有练习<表格行mouse经过时高亮显示>http://www.cnblogs.com/insus/p/3715733.html ,今天有奇想,是否可以实现mouse ...
- MVC实现更新数据库的数据
经过一系列MVC的练习,如数据库的数据显示,添加,删除等,还差一个功能,就是更新,那本次练习的是MVC对数据库的数据进行更新. 写好更新的存过程: 有了存储过程,可以写实体(Entity)的方法了.写 ...
- Http请求帮助类
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ...
- C#:ORM--实体框架EF(entity framework)(2)
有三种不同的模式可以在您的应用中使用EF框架 Database First Code First ModelFirst Db-First 在DbFirst时,你使用VS中的EDM向导或使用EF命令来从 ...
- Expression<Func<T>>和Func<T>
以前用EF的时候,由于where的时候有Expression<Func<T>>和Func<T>两种查询条件,误用了Func<T>那个重载,后来还想通过f ...
- 【 js 基础 】【 源码学习 】 深浅拷贝
underscore的源码中,有很多地方用到了 Array.prototype.slice() 方法,但是并没有传参,实际上只是为了返回数组的副本,例如 underscore 中 clone 的方法: ...