diff --git a/lcci/16.04.Tic-Tac-Toe/README.md b/lcci/16.04.Tic-Tac-Toe/README.md
index bd3c28614bd6b..e073f53647620 100644
--- a/lcci/16.04.Tic-Tac-Toe/README.md
+++ b/lcci/16.04.Tic-Tac-Toe/README.md
@@ -5,6 +5,7 @@
## 题目描述
+
设计一个算法,判断玩家是否赢了井字游戏。输入是一个 N x N 的数组棋盘,由字符" ","X"和"O"组成,其中字符" "代表一个空位。
以下是井字游戏的规则:
@@ -39,6 +40,17 @@
## 解法
+
+**方法一:计数**
+
+对于每个格子,如果是 `X`,我们不妨将计数加 1ドル,ドル如果是 `O`,我们不妨将计数减 1ドル$。那么当某个格子所在的行、列或者对角线的计数的绝对值等于 $n$ 时,说明当前玩家在该行、列或者对角线上放置了 $n$ 个相同字符,游戏结束,返回对应的字符即可。
+
+具体地,我们用一个长度为 $n$ 的一维数组 $rows$ 和 $cols$ 分别表示每一行和每一列的计数,用 $dg$ 和 $udg$ 分别表示两个对角线的计数。当玩家放置一个字符到 $(i, j)$ 时,根据字符是 `X` 还是 `O`,更新数组 $rows,ドル$cols,ドル$dg$ 以及 $udg$ 中对应元素的值。每次更新后,我们判断对应的元素的值的绝对值是否等于 $n,ドル如果等于 $n,ドル则说明当前玩家在行、列或者对角线上放置了 $n$ 个相同字符,游戏结束,返回对应的字符即可。
+
+最后,我们遍历整个棋盘,如果棋盘中存在字符 ` `,说明游戏还未结束,返回 `Pending`,否则返回 `Draw`。
+
+时间复杂度 $O(n^2),ドル空间复杂度 $O(n)$。其中 $n$ 是棋盘的边长。
+
### **Python3**
@@ -46,7 +58,28 @@
```python
-
+class Solution:
+ def tictactoe(self, board: List[str]) -> str:
+ n = len(board)
+ rows = [0] * n
+ cols = [0] * n
+ dg = udg = 0
+ has_empty_grid = False
+ for i, row in enumerate(board):
+ for j, c in enumerate(row):
+ v = 1 if c == 'X' else -1
+ if c == ' ':
+ has_empty_grid = True
+ v = 0
+ rows[i] += v
+ cols[j] += v
+ if i == j:
+ dg += v
+ if i + j + 1 == n:
+ udg += v
+ if abs(rows[i]) == n or abs(cols[j]) == n or abs(dg) == n or abs(udg) == n:
+ return c
+ return 'Pending' if has_empty_grid else 'Draw'
```
### **Java**
@@ -54,7 +87,159 @@
```java
+class Solution {
+ public String tictactoe(String[] board) {
+ int n = board.length;
+ int[] rows = new int[n];
+ int[] cols = new int[n];
+ int dg = 0, udg = 0;
+ boolean hasEmptyGrid = false;
+ for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + char c = board[i].charAt(j); + if (c == ' ') { + hasEmptyGrid = true; + continue; + } + int v = c == 'X' ? 1 : -1; + rows[i] += v; + cols[j] += v; + if (i == j) { + dg += v; + } + if (i + j + 1 == n) { + udg += v; + } + if (Math.abs(rows[i]) == n || Math.abs(cols[j]) == n || Math.abs(dg) == n + || Math.abs(udg) == n) { + return String.valueOf(c); + } + } + } + return hasEmptyGrid ? "Pending" : "Draw"; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + string tictactoe(vector& board) {
+ int n = board.size();
+ vector rows(n), cols(n);
+ int dg = 0, udg = 0;
+ bool hasEmptyGrid = false;
+ for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + char c = board[i][j]; + if (c == ' ') { + hasEmptyGrid = true; + continue; + } + int v = c == 'X' ? 1 : -1; + rows[i] += v; + cols[j] += v; + if (i == j) { + dg += v; + } + if (i + j + 1 == n) { + udg += v; + } + if (abs(rows[i]) == n || abs(cols[j]) == n || abs(dg) == n || abs(udg) == n) { + return string(1, c); + } + } + } + return hasEmptyGrid ? "Pending" : "Draw"; + } +}; +``` + +### **Go** + +```go +func tictactoe(board []string) string { + n := len(board) + rows := make([]int, n) + cols := make([]int, n) + dg, udg := 0, 0 + hasEmptyGrid := false + for i, row := range board { + for j, c := range row { + if c == ' ' { + hasEmptyGrid = true + continue + } + v := 1 + if c == 'O' { + v = -1 + } + rows[i] += v + cols[j] += v + if i == j { + dg += v + } + if i+j == n-1 { + udg += v + } + if abs(rows[i]) == n || abs(cols[j]) == n || abs(dg) == n || abs(udg) == n { + return string(c) + } + } + } + if hasEmptyGrid { + return "Pending" + } + return "Draw" +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} +``` +### **TypeScript** + +```ts +function tictactoe(board: string[]): string { + const n = board.length; + const rows = Array(n).fill(0); + const cols = Array(n).fill(0); + let [dg, udg] = [0, 0]; + let hasEmptyGrid = false; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < n; ++j) { + const c = board[i][j]; + if (c === ' ') { + hasEmptyGrid = true; + continue; + } + const v = c === 'X' ? 1 : -1; + rows[i] += v; + cols[j] += v; + if (i === j) { + dg += v; + } + if (i + j === n - 1) { + udg += v; + } + if ( + Math.abs(rows[i]) === n || + Math.abs(cols[j]) === n || + Math.abs(dg) === n || + Math.abs(udg) === n + ) { + return c; + } + } + } + return hasEmptyGrid ? 'Pending' : 'Draw'; +} ``` ### **...** diff --git a/lcci/16.04.Tic-Tac-Toe/README_EN.md b/lcci/16.04.Tic-Tac-Toe/README_EN.md index 36fe3270d0b8e..6cddbe56c249a 100644 --- a/lcci/16.04.Tic-Tac-Toe/README_EN.md +++ b/lcci/16.04.Tic-Tac-Toe/README_EN.md @@ -51,18 +51,201 @@ ## Solutions +**Solution 1: Counting** + +For each cell, if it is `X`, we can add 1ドル$ to the count; if it is `O`, we can subtract 1ドル$ from the count. When the absolute value of the count of a row, column, or diagonal equals $n,ドル it means that the current player has placed $n$ identical characters in that row, column, or diagonal, and the game is over. We can return the corresponding character. + +Specifically, we use a one-dimensional array $rows$ and $cols$ of length $n$ to represent the count of each row and column, and use $dg$ and $udg$ to represent the count of the two diagonals. When a player places a character at $(i, j),ドル we update the corresponding elements in the arrays $rows,ドル $cols,ドル $dg,ドル and $udg$ based on whether the character is `X` or `O`. After each update, we check whether the absolute value of the corresponding element equals $n$. If it does, it means that the current player has placed $n$ identical characters in that row, column, or diagonal, and the game is over. We can return the corresponding character. + +Finally, we traverse the entire board. If there is a character ` `, it means that the game is not over yet, and we return `Pending`. Otherwise, we return `Draw`. + +The time complexity is $O(n^2),ドル and the space complexity is $O(n),ドル where $n$ is the side length of the board. + ### **Python3** ```python - +class Solution: + def tictactoe(self, board: List[str]) -> str:
+ n = len(board)
+ rows = [0] * n
+ cols = [0] * n
+ dg = udg = 0
+ has_empty_grid = False
+ for i, row in enumerate(board):
+ for j, c in enumerate(row):
+ v = 1 if c == 'X' else -1
+ if c == ' ':
+ has_empty_grid = True
+ v = 0
+ rows[i] += v
+ cols[j] += v
+ if i == j:
+ dg += v
+ if i + j + 1 == n:
+ udg += v
+ if abs(rows[i]) == n or abs(cols[j]) == n or abs(dg) == n or abs(udg) == n:
+ return c
+ return 'Pending' if has_empty_grid else 'Draw'
```
### **Java**
```java
+class Solution {
+ public String tictactoe(String[] board) {
+ int n = board.length;
+ int[] rows = new int[n];
+ int[] cols = new int[n];
+ int dg = 0, udg = 0;
+ boolean hasEmptyGrid = false;
+ for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + char c = board[i].charAt(j); + if (c == ' ') { + hasEmptyGrid = true; + continue; + } + int v = c == 'X' ? 1 : -1; + rows[i] += v; + cols[j] += v; + if (i == j) { + dg += v; + } + if (i + j + 1 == n) { + udg += v; + } + if (Math.abs(rows[i]) == n || Math.abs(cols[j]) == n || Math.abs(dg) == n + || Math.abs(udg) == n) { + return String.valueOf(c); + } + } + } + return hasEmptyGrid ? "Pending" : "Draw"; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + string tictactoe(vector& board) {
+ int n = board.size();
+ vector rows(n), cols(n);
+ int dg = 0, udg = 0;
+ bool hasEmptyGrid = false;
+ for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + char c = board[i][j]; + if (c == ' ') { + hasEmptyGrid = true; + continue; + } + int v = c == 'X' ? 1 : -1; + rows[i] += v; + cols[j] += v; + if (i == j) { + dg += v; + } + if (i + j + 1 == n) { + udg += v; + } + if (abs(rows[i]) == n || abs(cols[j]) == n || abs(dg) == n || abs(udg) == n) { + return string(1, c); + } + } + } + return hasEmptyGrid ? "Pending" : "Draw"; + } +}; +``` + +### **Go** + +```go +func tictactoe(board []string) string { + n := len(board) + rows := make([]int, n) + cols := make([]int, n) + dg, udg := 0, 0 + hasEmptyGrid := false + for i, row := range board { + for j, c := range row { + if c == ' ' { + hasEmptyGrid = true + continue + } + v := 1 + if c == 'O' { + v = -1 + } + rows[i] += v + cols[j] += v + if i == j { + dg += v + } + if i+j == n-1 { + udg += v + } + if abs(rows[i]) == n || abs(cols[j]) == n || abs(dg) == n || abs(udg) == n { + return string(c) + } + } + } + if hasEmptyGrid { + return "Pending" + } + return "Draw" +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} +``` + +### **TypeScript** +```ts +function tictactoe(board: string[]): string { + const n = board.length; + const rows = Array(n).fill(0); + const cols = Array(n).fill(0); + let [dg, udg] = [0, 0]; + let hasEmptyGrid = false; + for (let i = 0; i < n; ++i) { + for (let j = 0; j < n; ++j) { + const c = board[i][j]; + if (c === ' ') { + hasEmptyGrid = true; + continue; + } + const v = c === 'X' ? 1 : -1; + rows[i] += v; + cols[j] += v; + if (i === j) { + dg += v; + } + if (i + j === n - 1) { + udg += v; + } + if ( + Math.abs(rows[i]) === n || + Math.abs(cols[j]) === n || + Math.abs(dg) === n || + Math.abs(udg) === n + ) { + return c; + } + } + } + return hasEmptyGrid ? 'Pending' : 'Draw'; +} ``` ### **...** diff --git a/lcci/16.04.Tic-Tac-Toe/Solution.cpp b/lcci/16.04.Tic-Tac-Toe/Solution.cpp new file mode 100644 index 0000000000000..f165fc4fe77b6 --- /dev/null +++ b/lcci/16.04.Tic-Tac-Toe/Solution.cpp @@ -0,0 +1,31 @@ +class Solution { +public: + string tictactoe(vector& board) {
+ int n = board.size();
+ vector rows(n), cols(n);
+ int dg = 0, udg = 0;
+ bool hasEmptyGrid = false;
+ for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + char c = board[i][j]; + if (c == ' ') { + hasEmptyGrid = true; + continue; + } + int v = c == 'X' ? 1 : -1; + rows[i] += v; + cols[j] += v; + if (i == j) { + dg += v; + } + if (i + j + 1 == n) { + udg += v; + } + if (abs(rows[i]) == n || abs(cols[j]) == n || abs(dg) == n || abs(udg) == n) { + return string(1, c); + } + } + } + return hasEmptyGrid ? "Pending" : "Draw"; + } +}; \ No newline at end of file diff --git a/lcci/16.04.Tic-Tac-Toe/Solution.go b/lcci/16.04.Tic-Tac-Toe/Solution.go new file mode 100644 index 0000000000000..402e56ae2cc77 --- /dev/null +++ b/lcci/16.04.Tic-Tac-Toe/Solution.go @@ -0,0 +1,41 @@ +func tictactoe(board []string) string { + n := len(board) + rows := make([]int, n) + cols := make([]int, n) + dg, udg := 0, 0 + hasEmptyGrid := false + for i, row := range board { + for j, c := range row { + if c == ' ' { + hasEmptyGrid = true + continue + } + v := 1 + if c == 'O' { + v = -1 + } + rows[i] += v + cols[j] += v + if i == j { + dg += v + } + if i+j == n-1 { + udg += v + } + if abs(rows[i]) == n || abs(cols[j]) == n || abs(dg) == n || abs(udg) == n { + return string(c) + } + } + } + if hasEmptyGrid { + return "Pending" + } + return "Draw" +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} \ No newline at end of file diff --git a/lcci/16.04.Tic-Tac-Toe/Solution.java b/lcci/16.04.Tic-Tac-Toe/Solution.java new file mode 100644 index 0000000000000..5ff5a378eff05 --- /dev/null +++ b/lcci/16.04.Tic-Tac-Toe/Solution.java @@ -0,0 +1,32 @@ +class Solution { + public String tictactoe(String[] board) { + int n = board.length; + int[] rows = new int[n]; + int[] cols = new int[n]; + int dg = 0, udg = 0; + boolean hasEmptyGrid = false; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + char c = board[i].charAt(j); + if (c == ' ') { + hasEmptyGrid = true; + continue; + } + int v = c == 'X' ? 1 : -1; + rows[i] += v; + cols[j] += v; + if (i == j) { + dg += v; + } + if (i + j + 1 == n) { + udg += v; + } + if (Math.abs(rows[i]) == n || Math.abs(cols[j]) == n || Math.abs(dg) == n + || Math.abs(udg) == n) { + return String.valueOf(c); + } + } + } + return hasEmptyGrid ? "Pending" : "Draw"; + } +} \ No newline at end of file diff --git a/lcci/16.04.Tic-Tac-Toe/Solution.py b/lcci/16.04.Tic-Tac-Toe/Solution.py new file mode 100644 index 0000000000000..c4c47432aac3d --- /dev/null +++ b/lcci/16.04.Tic-Tac-Toe/Solution.py @@ -0,0 +1,27 @@ +class Solution: + def tictactoe(self, board: List[str]) -> str:
+ n = len(board)
+ rows = [0] * n
+ cols = [0] * n
+ dg = udg = 0
+ has_empty_grid = False
+ for i, row in enumerate(board):
+ for j, c in enumerate(row):
+ v = 1 if c == 'X' else -1
+ if c == ' ':
+ has_empty_grid = True
+ v = 0
+ rows[i] += v
+ cols[j] += v
+ if i == j:
+ dg += v
+ if i + j + 1 == n:
+ udg += v
+ if (
+ abs(rows[i]) == n
+ or abs(cols[j]) == n
+ or abs(dg) == n
+ or abs(udg) == n
+ ):
+ return c
+ return 'Pending' if has_empty_grid else 'Draw'
diff --git a/lcci/16.04.Tic-Tac-Toe/Solution.ts b/lcci/16.04.Tic-Tac-Toe/Solution.ts
new file mode 100644
index 0000000000000..fc04dde213cb2
--- /dev/null
+++ b/lcci/16.04.Tic-Tac-Toe/Solution.ts
@@ -0,0 +1,34 @@
+function tictactoe(board: string[]): string {
+ const n = board.length;
+ const rows = Array(n).fill(0);
+ const cols = Array(n).fill(0);
+ let [dg, udg] = [0, 0];
+ let hasEmptyGrid = false;
+ for (let i = 0; i < n; ++i) {
+ for (let j = 0; j < n; ++j) {
+ const c = board[i][j];
+ if (c === ' ') {
+ hasEmptyGrid = true;
+ continue;
+ }
+ const v = c === 'X' ? 1 : -1;
+ rows[i] += v;
+ cols[j] += v;
+ if (i === j) {
+ dg += v;
+ }
+ if (i + j === n - 1) {
+ udg += v;
+ }
+ if (
+ Math.abs(rows[i]) === n ||
+ Math.abs(cols[j]) === n ||
+ Math.abs(dg) === n ||
+ Math.abs(udg) === n
+ ) {
+ return c;
+ }
+ }
+ }
+ return hasEmptyGrid ? 'Pending' : 'Draw';
+}