LC 794. 有效的井字游戏
题目描述
这是 LeetCode 上的 794. 有效的井字游戏 ,难度为 中等。
给你一个字符串数组 board
表示井字游戏的棋盘。当且仅当在井字游戏过程中,棋盘有可能达到 board
所显示的状态时,才返回 true
。
井字游戏的棋盘是一个 3 x 3
数组,由字符 ' '
,'X'
和 'O'
组成。字符 ' '
代表一个空位。
以下是井字游戏的规则:
- 玩家轮流将字符放入空位(
' '
)中。 - 玩家 $1$ 总是放字符
'X'
,而玩家 $2$ 总是放字符'O'
。 - ‘X’ 和 ‘O’ 只允许放置在空位中,不允许对已放有字符的位置进行填充。
- 当有 $3$ 个相同(且非空)的字符填充任何行、列或对角线时,游戏结束。
- 当所有位置非空时,也算为游戏结束。
- 如果游戏结束,玩家不允许再放置字符。
示例 1:1
2
3
4
5输入:board = ["O "," "," "]
输出:false
解释:玩家 1 总是放字符 "X" 。
示例 2:1
2
3
4
5输入:board = ["XOX"," X "," "]
输出:false
解释:玩家应该轮流放字符。
示例 3:1
2
3输入:board = ["XXX"," ","OOO"]
输出:false
示例 4:1
2
3输入:board = ["XOX","O O","XOX"]
输出:true
提示:
board.length == 3
board[i].length == 3
board[i][j]
为'X'
、'O'
或' '
分情况讨论
给定的棋盘大小固定,对于无效情况进行分情况讨论即可:
- 由于
X
先手,O
后手,两者轮流下子。因此O
的数量不会超过X
,且两者数量差不会超过 $1$,否则为无效局面; - 若局面是
X
获胜,导致该局面的最后一个子必然是X
,此时必然有X
数量大于O
(X
为先手),否则为无效局面; - 若局面是
O
获胜,导致该局面的最后一个子必然是O
,此时必然有X
数量等于O
(X
为先手),否则为无效局面; - 局面中不可能出现两者同时赢(其中一方赢后,游戏结束)。
代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34class Solution {
public boolean validTicTacToe(String[] board) {
char[][] cs = new char[3][3];
int x = 0, o = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
char c = board[i].charAt(j);
if (c == 'X') x++;
else if (c == 'O') o++;
cs[i][j] = c;
}
}
boolean a = check(cs, 'X'), b = check(cs, 'O');
if (o > x || x - o > 1) return false;
if (a && x <= o) return false;
if (b && o != x) return false;
if (a && b) return false;
return true;
}
boolean check(char[][] cs, char c) {
for (int i = 0; i < 3; i++) {
if (cs[i][0] == c && cs[i][1] == c && cs[i][2] == c) return true;
if (cs[0][i] == c && cs[1][i] == c && cs[2][i] == c) return true;
}
boolean a = true, b = true;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == j) a &= cs[i][j] == c;
if (i + j == 2) b &= cs[i][j] == c;
}
}
return a || b;
}
}
- 时间复杂度:棋盘大小固定,遍历棋盘次数为常数。复杂度为 $O(C)$
- 空间复杂度:使用了 $char$ 二维数组对 $board$ 进行转存,复杂度为 $O(C)$;全程使用
charAt
的话复杂度为 $O(1)$
最后
这是我们「刷穿 LeetCode」系列文章的第 No.794
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!