Skip to content

Commit f491940

Browse files
committed
36
1 parent b995ea5 commit f491940

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed

SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@
3636
* [33. Search in Rotated Sorted Array](leetCode-33-Search-in-Rotated-Sorted-Array.md)
3737
* [34. Find First and Last Position of Element in Sorted Array](leetCode-34-Find-First-and-Last-Position-of-Element-in-Sorted-Array.md)
3838
* [35. Search Insert Position](leetCode-35-Search-Insert-Position.md)
39+
* [36. Valid Sudoku](leetCode-36-Valid-Sudoku.md)
3940
* [79. Word Search](leetCode-79-Word-Search.md)

leetCode-36-Valid-Sudoku.md

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# 题目描述(中等难度)
2+
3+
![](https://windliang.oss-cn-beijing.aliyuncs.com/36.png)
4+
5+
一个 9 * 9 的数独的棋盘。判断已经写入数字的棋盘是不是合法。需要满足下边三点,
6+
7+
* 每一行的数字不能重复
8+
9+
* 每一列的数字不能重复
10+
* 9 个 3 * 3 的小棋盘中的数字也不能重复。
11+
12+
只能是 1 - 9 中的数字,不需要考虑数独最后能不能填满。
13+
14+
# 解法一 暴力解法
15+
16+
需要满足三条,那就一条一条判断。
17+
18+
```java
19+
public boolean isValidSudoku(char[][] board) {
20+
//判断每一行
21+
for (int i = 0; i < 9; i++) {
22+
if (!isValidRows(board[i])) {
23+
return false;
24+
}
25+
}
26+
//判断每一列
27+
for (int i = 0; i < 9; i++) {
28+
if (!isValidCols(i, board)) {
29+
return false;
30+
}
31+
}
32+
//判断每个小棋盘
33+
for (int i = 0; i < 9; i = i + 3) {
34+
for (int j = 0; j < 9; j = j + 3) {
35+
if (!isValidSmall(i, j, board)) {
36+
return false;
37+
}
38+
}
39+
40+
}
41+
return true;
42+
}
43+
44+
public boolean isValidRows(char[] board) {
45+
HashMap<Character, Integer> hashMap = new HashMap<>();
46+
for (char c : board) {
47+
if (c != '.') {
48+
if (hashMap.getOrDefault(c, 0) != 0) {
49+
return false;
50+
} else {
51+
hashMap.put(c, 1);
52+
}
53+
}
54+
}
55+
return true;
56+
}
57+
58+
public boolean isValidCols(int col, char[][] board) {
59+
HashMap<Character, Integer> hashMap = new HashMap<>();
60+
for (int i = 0; i < 9; i++) {
61+
char c = board[i][col];
62+
if (c != '.') {
63+
if (hashMap.getOrDefault(c, 0) != 0) {
64+
return false;
65+
} else {
66+
hashMap.put(c, 1);
67+
}
68+
}
69+
}
70+
return true;
71+
}
72+
73+
public boolean isValidSmall(int row, int col, char[][] board) {
74+
HashMap<Character, Integer> hashMap = new HashMap<>();
75+
for (int i = 0; i < 3; i++) {
76+
for (int j = 0; j < 3; j++) {
77+
char c = board[row + i][col + j];
78+
if (c != '.') {
79+
if (hashMap.getOrDefault(c, 0) != 0) {
80+
return false;
81+
} else {
82+
hashMap.put(c, 1);
83+
}
84+
}
85+
}
86+
}
87+
return true;
88+
}
89+
```
90+
91+
时间复杂度:整个棋盘访问了三次,如果棋盘大小是 n,那么就是 3n。也就是 O(n)。
92+
93+
空间复杂度:O(1)。
94+
95+
# 解法二
96+
97+
参考[这里](https://leetcode.com/problems/valid-sudoku/discuss/15472/Short%2BSimple-Java-using-Strings),上边的算法遍历了三遍,我们能不能只遍历一遍。
98+
99+
我们可以这样想一下,如果有一副纸牌,怎么看它有没有重复的?
100+
101+
第一种我们可以像之前一样,第一遍先看红桃,再看黑桃,再看方片,再看梅花,这样就看了四遍。我们其实可以每拿到一张牌,就把它放在一个位置,我们把一类放在同一位置。红桃放在一起,黑桃放在一起……放的过程中如果有重复的就可以结束了。
102+
103+
在这里的话,我们就可以把第一行的放在一起,第二行的放在一起……第一列的放在一起,第二列的放在一起……第一个小棋盘的放在一起,第二个小棋盘的放在一起……
104+
105+
我们用 HashSet 实现放在一起的作用,但是这样的话总共就是 9 行,9 列,9 个小棋盘,27 个 HashSet 了。我们其实可以在放的时候标志一下,例如
106+
107+
* 如果第 4 行有一个数字 8,我们就 (8)4,把 "(8)4"放进去。
108+
* 如果第 5 行有一个数字 6,我们就 5(6),把 "5(6)"放进去。
109+
* 小棋盘看成一个整体,总共是 9 个,3 行 3 列,如果第 2 行第 1 列的小棋盘里有个数字 3,我们就把 "2(3)1" 放进去。
110+
111+
这样 1 个 HashSet 就够了。
112+
113+
```java
114+
public boolean isValidSudoku(char[][] board) {
115+
Set seen = new HashSet();
116+
for (int i=0; i<9; ++i) {
117+
for (int j=0; j<9; ++j) {
118+
if (board[i][j] != '.') {
119+
String b = "(" + board[i][j] + ")";
120+
if (!seen.add(b + i) || !seen.add(j + b) || !seen.add(i/3 + b + j/3))
121+
return false;
122+
}
123+
}
124+
}
125+
return true;
126+
}
127+
```
128+
129+
时间复杂度:如果棋盘大小总共是 n,那么只遍历了一次,就是 O(n)。
130+
131+
空间复杂度:如果棋盘大小总共是 n,最坏的情况就是每个地方都有数字,就需要存三次,O(n)。
132+
133+
其实,想到了标识,其实我们可以标识的更彻底些,直接写出来。
134+
135+
```java
136+
public boolean isValidSudoku(char[][] board) {
137+
Set seen = new HashSet();
138+
for (int i=0; i<9; ++i) {
139+
for (int j=0; j<9; ++j) {
140+
char number = board[i][j];
141+
if (number != '.')
142+
if (!seen.add(number + " in row " + i) ||
143+
!seen.add(number + " in column " + j) ||
144+
!seen.add(number + " in block " + i/3 + "-" + j/3))
145+
return false;
146+
}
147+
}
148+
return true;
149+
}
150+
```
151+
152+
#
153+
154+
第二种解法的作者太太聪明了!自己规定格式这种思想,很棒。

0 commit comments

Comments
 (0)