Skip to content

Commit 10e1921

Browse files
authored
feat: add solutions to lcci problem: No.16.04 (#1760)
No.16.04.Tic-Tac-Toe
1 parent 28646b0 commit 10e1921

File tree

7 files changed

+535
-2
lines changed

7 files changed

+535
-2
lines changed

lcci/16.04.Tic-Tac-Toe/README.md

+186-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
## 题目描述
66

77
<!-- 这里写题目描述 -->
8+
89
<p>设计一个算法,判断玩家是否赢了井字游戏。输入是一个 N x N 的数组棋盘,由字符&quot; &quot;&quot;X&quot;&quot;O&quot;组成,其中字符&quot; &quot;代表一个空位。</p>
910
<p>以下是井字游戏的规则:</p>
1011
<ul>
@@ -39,22 +40,206 @@
3940
## 解法
4041

4142
<!-- 这里可写通用的实现逻辑 -->
43+
44+
**方法一:计数**
45+
46+
对于每个格子,如果是 `X`,我们不妨将计数加 $1$,如果是 `O`,我们不妨将计数减 $1$。那么当某个格子所在的行、列或者对角线的计数的绝对值等于 $n$ 时,说明当前玩家在该行、列或者对角线上放置了 $n$ 个相同字符,游戏结束,返回对应的字符即可。
47+
48+
具体地,我们用一个长度为 $n$ 的一维数组 $rows$ 和 $cols$ 分别表示每一行和每一列的计数,用 $dg$ 和 $udg$ 分别表示两个对角线的计数。当玩家放置一个字符到 $(i, j)$ 时,根据字符是 `X` 还是 `O`,更新数组 $rows$,$cols$,$dg$ 以及 $udg$ 中对应元素的值。每次更新后,我们判断对应的元素的值的绝对值是否等于 $n$,如果等于 $n$,则说明当前玩家在行、列或者对角线上放置了 $n$ 个相同字符,游戏结束,返回对应的字符即可。
49+
50+
最后,我们遍历整个棋盘,如果棋盘中存在字符 ` `,说明游戏还未结束,返回 `Pending`,否则返回 `Draw`
51+
52+
时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 是棋盘的边长。
53+
4254
<!-- tabs:start -->
4355

4456
### **Python3**
4557

4658
<!-- 这里可写当前语言的特殊实现逻辑 -->
4759

4860
```python
49-
61+
class Solution:
62+
def tictactoe(self, board: List[str]) -> str:
63+
n = len(board)
64+
rows = [0] * n
65+
cols = [0] * n
66+
dg = udg = 0
67+
has_empty_grid = False
68+
for i, row in enumerate(board):
69+
for j, c in enumerate(row):
70+
v = 1 if c == 'X' else -1
71+
if c == ' ':
72+
has_empty_grid = True
73+
v = 0
74+
rows[i] += v
75+
cols[j] += v
76+
if i == j:
77+
dg += v
78+
if i + j + 1 == n:
79+
udg += v
80+
if abs(rows[i]) == n or abs(cols[j]) == n or abs(dg) == n or abs(udg) == n:
81+
return c
82+
return 'Pending' if has_empty_grid else 'Draw'
5083
```
5184

5285
### **Java**
5386

5487
<!-- 这里可写当前语言的特殊实现逻辑 -->
5588

5689
```java
90+
class Solution {
91+
public String tictactoe(String[] board) {
92+
int n = board.length;
93+
int[] rows = new int[n];
94+
int[] cols = new int[n];
95+
int dg = 0, udg = 0;
96+
boolean hasEmptyGrid = false;
97+
for (int i = 0; i < n; ++i) {
98+
for (int j = 0; j < n; ++j) {
99+
char c = board[i].charAt(j);
100+
if (c == ' ') {
101+
hasEmptyGrid = true;
102+
continue;
103+
}
104+
int v = c == 'X' ? 1 : -1;
105+
rows[i] += v;
106+
cols[j] += v;
107+
if (i == j) {
108+
dg += v;
109+
}
110+
if (i + j + 1 == n) {
111+
udg += v;
112+
}
113+
if (Math.abs(rows[i]) == n || Math.abs(cols[j]) == n || Math.abs(dg) == n
114+
|| Math.abs(udg) == n) {
115+
return String.valueOf(c);
116+
}
117+
}
118+
}
119+
return hasEmptyGrid ? "Pending" : "Draw";
120+
}
121+
}
122+
```
123+
124+
### **C++**
125+
126+
```cpp
127+
class Solution {
128+
public:
129+
string tictactoe(vector<string>& board) {
130+
int n = board.size();
131+
vector<int> rows(n), cols(n);
132+
int dg = 0, udg = 0;
133+
bool hasEmptyGrid = false;
134+
for (int i = 0; i < n; ++i) {
135+
for (int j = 0; j < n; ++j) {
136+
char c = board[i][j];
137+
if (c == ' ') {
138+
hasEmptyGrid = true;
139+
continue;
140+
}
141+
int v = c == 'X' ? 1 : -1;
142+
rows[i] += v;
143+
cols[j] += v;
144+
if (i == j) {
145+
dg += v;
146+
}
147+
if (i + j + 1 == n) {
148+
udg += v;
149+
}
150+
if (abs(rows[i]) == n || abs(cols[j]) == n || abs(dg) == n || abs(udg) == n) {
151+
return string(1, c);
152+
}
153+
}
154+
}
155+
return hasEmptyGrid ? "Pending" : "Draw";
156+
}
157+
};
158+
```
159+
160+
### **Go**
161+
162+
```go
163+
func tictactoe(board []string) string {
164+
n := len(board)
165+
rows := make([]int, n)
166+
cols := make([]int, n)
167+
dg, udg := 0, 0
168+
hasEmptyGrid := false
169+
for i, row := range board {
170+
for j, c := range row {
171+
if c == ' ' {
172+
hasEmptyGrid = true
173+
continue
174+
}
175+
v := 1
176+
if c == 'O' {
177+
v = -1
178+
}
179+
rows[i] += v
180+
cols[j] += v
181+
if i == j {
182+
dg += v
183+
}
184+
if i+j == n-1 {
185+
udg += v
186+
}
187+
if abs(rows[i]) == n || abs(cols[j]) == n || abs(dg) == n || abs(udg) == n {
188+
return string(c)
189+
}
190+
}
191+
}
192+
if hasEmptyGrid {
193+
return "Pending"
194+
}
195+
return "Draw"
196+
}
197+
198+
func abs(x int) int {
199+
if x < 0 {
200+
return -x
201+
}
202+
return x
203+
}
204+
```
57205

206+
### **TypeScript**
207+
208+
```ts
209+
function tictactoe(board: string[]): string {
210+
const n = board.length;
211+
const rows = Array(n).fill(0);
212+
const cols = Array(n).fill(0);
213+
let [dg, udg] = [0, 0];
214+
let hasEmptyGrid = false;
215+
for (let i = 0; i < n; ++i) {
216+
for (let j = 0; j < n; ++j) {
217+
const c = board[i][j];
218+
if (c === ' ') {
219+
hasEmptyGrid = true;
220+
continue;
221+
}
222+
const v = c === 'X' ? 1 : -1;
223+
rows[i] += v;
224+
cols[j] += v;
225+
if (i === j) {
226+
dg += v;
227+
}
228+
if (i + j === n - 1) {
229+
udg += v;
230+
}
231+
if (
232+
Math.abs(rows[i]) === n ||
233+
Math.abs(cols[j]) === n ||
234+
Math.abs(dg) === n ||
235+
Math.abs(udg) === n
236+
) {
237+
return c;
238+
}
239+
}
240+
}
241+
return hasEmptyGrid ? 'Pending' : 'Draw';
242+
}
58243
```
59244

60245
### **...**

0 commit comments

Comments
 (0)