【LeetCode】数独
判断一个数独是否合法,未填的空格用字符 ' . ' 表示。该数独有解并不是必要的。
e.g. 如图合法数独,输入
["53..7....","6..195...",".98....6.","8...6...3","4..8.3..1","7...2...6",".6....28.","...419..5","....8..79"]
返回 true。
我依然使用死办法解决,而且进行了输入合法性判断,即必须为 1 ~ 9 的数字或 ' . ' 。
bool isValidSudoku(vector<vector<char>>& board) {
vector<char> row, column, subbox;
for (int i = ; i < ; ++i) {
row.clear();
column.clear();
row = board[i];
if (!isValid(row))
return false;
for (int j = ; j < ; ++j) {
column.push_back(board[j][i]);
}
if (!isValid(column))
return false;
}
for (int i = ; i <= ; i = i + ) {
for (int j = ; j <= ; j = j + ) {
subbox.clear();
subbox.push_back(board[i][j]); subbox.push_back(board[i][j+]); subbox.push_back(board[i][j+]);
subbox.push_back(board[i+][j]); subbox.push_back(board[i+][j+]); subbox.push_back(board[i+][j+]);
subbox.push_back(board[i+][j]); subbox.push_back(board[i+][j+]); subbox.push_back(board[i+][j+]);
if (!isValid(subbox))
return false;
}
}
return true;
} bool isValid(vector<char> &t) {
sort(t.begin(), t.end());
for (int i = ; i < ; ++i) {
if (((t[i] < '' || t[i] > '') && t[i] != '.') || (i > && t[i] == t[i - ] && t[i] != '.'))
return false;
}
return true;
}
答案巧妙的做法如下
bool isValidSudoku(vector<vector<char>>& board) {
bool row[][] = {false}, col[][] = {false}, box[][] = {false};
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
if (board[i][j] != '.') {
int num = board[i][j] - '' - , k = i / * + j / ;
if (row[i][num] || col[j][num] || box[k][num]) return false;
row[i][num] = col[j][num] = box[k][num] = true;
}
}
}
return true;
}
num = board[i][j] - '0' - 1 的思路就是用一个新 bool 型数组(初始化全为 false)判断原数组是否有重复元素。
k = i / 3 * 3 + j / 3 将原来 9 * 9 的方格映射到 3 * 3 的方格中!
0 | 1 | 2
3 | 4 | 5
6 | 7 | 8
例如 i = 5,j = 6 (第 5 行 第 6 列)时,k = 5 / 3 * 3 + 6 / 3 = 1 * 3 + 2 = 5,在 box[5][] 这个数组里进行判断。
这种方法更常规的用法见下。
这个Java实现也很巧妙
public boolean isValidSudoku(char[][] board) {
for(int i = 0; i < 9; i++) {
Set<Character> rows = new HashSet<>();
Set<Character> cols = new HashSet<>();
Set<Character> cubes = new HashSet<>();
for (int j = 0; j < 9; j++) {
if (board[i][j] != '.' && !rows.add(board[i][j])) return false;
if (board[j][i] != '.' && !cols.add(board[j][i])) return false;
int colStart = 3 * (i % 3), rowStart = 3 * (i / 3);
int colOffset = j % 3, rowOffset = j / 3; // 偏移
int row = rowStart + rowOffset, col = colStart + colOffset;
if (board[row][col] != '.' && !cubes.add(board[row][col]) ) return false;
}
}
return true;
}
HashSet 的 add(E e) 方法用于将指定元素添加到这个 HashSet,若此 Set 已经包含该元素,则直接返回 false。
% 和 / 操作符对于矩阵遍历问题很有帮助。
使用 % 作水平遍历,即计算列坐标偏移。因为 j 每增加 ,j % 3 也增加 然后重置。
使用 / 作竖直遍历,即计算行坐标偏移。因为 j 每增加 ,j / 3 才能增加 。
通过 0 ~ 8 的 j 即可遍历一个 9 * 9 矩阵的一个 3 * 3 子块。如何继续遍历下一个子块呢?就需要用外层循环 0 ~ 8 的 i 实现。
依然使用 % 水平遍历到下一个子块,colStart = 3 * (i % 3) ,× 3 是因为下一个子块在 3 列之后,第一个子块的起始是 (0, 0),第二个子块的起始是 (0, 3) 而不是 (0, 1)。
e.g.
i = 2 时,j 从 0 ~ 8,
rowStart = 3 * (2 / 3) = 0 colStart = 3 * (2 % 3) = 6
rowOffset = j / 3 = 0,0,0, 1,1,1, 2,2,2 colOffset = j % 3 = 0,1,2, 0,1,2, 0,1,2
对应了 board 矩阵中的
(0+0, 6+0) | (0+0, 6+1) | (0+0, 6+2) |
(0+1, 6+0) | (0+1, 6+1) | (0+1, 6+2) |
(0+2, 6+0) | (0+2, 6+1) | (0+2, 6+2) |
即
(0,6) | (0,7) | (0,8) |
(1,6) | (1,7) | (1,8) |
(2,6) | (2,7) | (2,8) |
这个 Sub-Box。
【LeetCode】数独的更多相关文章
- [LeetCode] Sudoku Solver 求解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
- [LeetCode] Valid Sudoku 验证数独
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...
- LeetCode:36. Valid Sudoku,数独是否有效
LeetCode:36. Valid Sudoku,数独是否有效 : 题目: LeetCode:36. Valid Sudoku 描述: Determine if a Sudoku is valid, ...
- LeetCode 37 Sudoku Solver(求解数独)
题目链接: https://leetcode.com/problems/sudoku-solver/?tab=Description Problem : 解决数独问题,给出一个二维数组,将这个数独 ...
- LeetCode 36 Valid Sudoku(合法的数独)
题目链接: https://leetcode.com/problems/valid-sudoku/?tab=Description 给出一个二维数组,数组大小为数独的大小,即9*9 其中,未填入 ...
- [LeetCode] “全排列”问题系列(一) - 用交换元素法生成全排列及其应用,例题: Permutations I 和 II, N-Queens I 和 II,数独问题
一.开篇 Permutation,排列问题.这篇博文以几道LeetCode的题目和引用剑指offer上的一道例题入手,小谈一下这种类型题目的解法. 二.上手 最典型的permutation题目是这样的 ...
- “全排列”问题系列(一)[LeetCode] - 用交换元素法生成全排列及其应用,例题: Permutations I 和 II, N-Queens I 和 II,数独问题
转:http://www.cnblogs.com/felixfang/p/3705754.html 一.开篇 Permutation,排列问题.这篇博文以几道LeetCode的题目和引用剑指offer ...
- Leetcode之回溯法专题-37. 解数独(Sudoku Solver)
Leetcode之回溯法专题-37. 解数独(Sudoku Solver) 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次.数字 1 ...
- [LeetCode] 37. Sudoku Solver 求解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy ...
- [LeetCode] 36. Valid Sudoku 验证数独
Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to th ...
随机推荐
- 用flvplayer.swf在网页中播放视频(网页中flash视频播放的实现)
原:http://blog.csdn.net/ricciozhang/article/details/46868201 由于公司项目的需求,需要在展示一些信息的时候能够播放视频,拿到这个要求,我就从最 ...
- Broken Keyboard (a.k.a. Beiju Text) 思路
问题:You’re typing a long text with a broken keyboard. Well it’s not so badly broken. The only problem ...
- idea 启动时报 error:java 无效的源发行版
说白了就是编译的版本不符合,有的地方是jdk1.7 有的地方是jdk1.8 所以你只要每个地方都保持一致就行. 每个地方!! 每个地方!! 每个地方!! 重要的设置说三遍! 以jdk1.7为例 fil ...
- 学习笔记18—circos应用集
一.在线画图(行列分别最大为75) 相信大家都听说过circos图,但是亲自画过的人可能就很少,这主要因为软件的安装和使用稍微有一点麻烦.其实,circos图也是可以在线绘制的,这样就简单多了!一起来 ...
- 新建ng工程
有问题多看官网文档https://www.angular.cn/guide/quickstart 1 在远程仓库建立 1个完全空的仓库,不要建立readme.MD ng cli创建时会创建readm ...
- 安装Linux系统的磁盘分区
●CentOS磁盘分区 分区顺序: "/"分区(逻辑) -> "/boot"分区(主分区) -> "swap"分区(逻辑) -& ...
- Python Selenium unittest+HTMLTestRunner实现 自动化测试及发送测试报告邮件
1.UI测试框架搭建-目录结构 2. 文件介绍 2.1.baseinfo->__init__.py 配置文件定义基础参数 #-*-coding:utf-8-*- #测试用例配置参数 base_u ...
- 完全二叉树的节点个数 Count Complete Tree Nodes
2018-09-25 16:36:25 问题描述: 问题求解: 单纯遍历了一遍,emmm,果然TLE. 解题思路就是比较左边树高度和右边树高度,如果相等,那么就是一个满二叉树,返回1 << ...
- 最简单的解决Chrome浏览器主页被hao123、360和2345篡改的方法是什么
最简单的解决Chrome浏览器主页被hao123.360和2345篡改的方法是什么 一.总结 一句话总结:打开chrome的安装目录,将chrome.exe改成chrome1.exe即可,然后发送一个 ...
- php爬虫最最最最简单教程
php爬虫最最最最简单教程 一.总结 一句话总结:用的爬虫框架,却是用的自己的例子(因为网站结构的变化,作者的例子不一定好用) 爬虫框架 自己例子 1.发现自己的运行效果和作者的不一样怎么办? 耐下性 ...