Skip to content

feat: add solutions to lc problem: No.1900 #4562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,41 +82,341 @@ tags:

<!-- solution:start -->

### 方法一
### 方法一:记忆化搜索 + 二进制枚举

我们定义一个函数 $\text{dfs}(l, r, n)$,表示在当前回合中,编号为 $l$ 和 $r$ 的运动员在 $n$ 名运动员中比拼的最早和最晚回合数。

函数 $\text{dfs}(l, r, n)$ 的执行逻辑如下:

1. 如果 $l + r = n - 1$,说明两名运动员在当前回合中比拼,返回 $[1, 1]$。
2. 如果 $f[l][r][n] \neq 0$,说明之前已经计算过这个状态,直接返回结果。
3. 初始化最早回合数为正无穷大,最晚回合数为负无穷大。
4. 计算当前回合中前半部分的运动员数目 $m = n / 2$。
5. 枚举前半部分的所有可能的胜者组合(使用二进制枚举),对于每一种组合:
- 根据当前组合确定哪些运动员获胜。
- 确定当前回合中编号为 $l$ 和 $r$ 的运动员在当前回合中的位置。
- 统计当前回合中编号为 $l$ 和 $r$ 的运动员在剩余运动员中的位置,记为 $a$ 和 $b$,以及剩余运动员的总数 $c$。
- 递归调用 $\text{dfs}(a, b, c)$,获取当前状态的最早和最晚回合数。
- 更新最早回合数和最晚回合数。
6. 将计算结果存储在 $f[l][r][n]$ 中,并返回最早和最晚回合数。

答案为 $\text{dfs}(\text{firstPlayer} - 1, \text{secondPlayer} - 1, n)$。

<!-- tabs:start -->

#### Python3

```python
@cache
def dfs(l: int, r: int, n: int):
if l + r == n - 1:
return [1, 1]
res = [inf, -inf]
m = n >> 1
for i in range(1 << m):
win = [False] * n
for j in range(m):
if i >> j & 1:
win[j] = True
else:
win[n - 1 - j] = True
if n & 1:
win[m] = True
win[n - 1 - l] = win[n - 1 - r] = False
win[l] = win[r] = True
a = b = c = 0
for j in range(n):
if j == l:
a = c
if j == r:
b = c
if win[j]:
c += 1
x, y = dfs(a, b, c)
res[0] = min(res[0], x + 1)
res[1] = max(res[1], y + 1)
return res


class Solution:
def earliestAndLatest(
self, n: int, firstPlayer: int, secondPlayer: int
) -> List[int]:
# dp[i][j][k] := (earliest, latest) pair w/ firstPlayer is i-th player from
# Front, secondPlayer is j-th player from end, and there're k people
@functools.lru_cache(None)
def dp(l: int, r: int, k: int) -> List[int]:
if l == r:
return [1, 1]
if l > r:
return dp(r, l, k)

a = math.inf
b = -math.inf

# Enumerate all possible positions
for i in range(1, l + 1):
for j in range(l - i + 1, r - i + 1):
if not l + r - k // 2 <= i + j <= (k + 1) // 2:
continue
x, y = dp(i, j, (k + 1) // 2)
a = min(a, x + 1)
b = max(b, y + 1)

return [a, b]

return dp(firstPlayer, n - secondPlayer + 1, n)
return dfs(firstPlayer - 1, secondPlayer - 1, n)
```

#### Java

```java
class Solution {
static int[][][] f = new int[30][30][31];

public int[] earliestAndLatest(int n, int firstPlayer, int secondPlayer) {
return dfs(firstPlayer - 1, secondPlayer - 1, n);
}

private int[] dfs(int l, int r, int n) {
if (f[l][r][n] != 0) {
return decode(f[l][r][n]);
}
if (l + r == n - 1) {
f[l][r][n] = encode(1, 1);
return new int[] {1, 1};
}
int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
int m = n >> 1;
for (int i = 0; i < (1 << m); i++) {
boolean[] win = new boolean[n];
for (int j = 0; j < m; j++) {
if (((i >> j) & 1) == 1) {
win[j] = true;
} else {
win[n - 1 - j] = true;
}
}
if ((n & 1) == 1) {
win[m] = true;
}
win[n - 1 - l] = win[n - 1 - r] = false;
win[l] = win[r] = true;
int a = 0, b = 0, c = 0;
for (int j = 0; j < n; j++) {
if (j == l) {
a = c;
}
if (j == r) {
b = c;
}
if (win[j]) {
c++;
}
}
int[] t = dfs(a, b, c);
min = Math.min(min, t[0] + 1);
max = Math.max(max, t[1] + 1);
}
f[l][r][n] = encode(min, max);
return new int[] {min, max};
}

private int encode(int x, int y) {
return (x << 8) | y;
}

private int[] decode(int val) {
return new int[] {val >> 8, val & 255};
}
}
```

#### C++

```cpp
int f[30][30][31];
class Solution {
public:
vector<int> earliestAndLatest(int n, int firstPlayer, int secondPlayer) {
return dfs(firstPlayer - 1, secondPlayer - 1, n);
}

private:
vector<int> dfs(int l, int r, int n) {
if (f[l][r][n] != 0) {
return decode(f[l][r][n]);
}
if (l + r == n - 1) {
f[l][r][n] = encode(1, 1);
return {1, 1};
}

int min = INT_MAX, max = INT_MIN;
int m = n >> 1;

for (int i = 0; i < (1 << m); i++) {
vector<bool> win(n, false);
for (int j = 0; j < m; j++) {
if ((i >> j) & 1) {
win[j] = true;
} else {
win[n - 1 - j] = true;
}
}
if (n & 1) {
win[m] = true;
}

win[n - 1 - l] = false;
win[n - 1 - r] = false;
win[l] = true;
win[r] = true;

int a = 0, b = 0, c = 0;
for (int j = 0; j < n; j++) {
if (j == l) a = c;
if (j == r) b = c;
if (win[j]) c++;
}

vector<int> t = dfs(a, b, c);
min = std::min(min, t[0] + 1);
max = std::max(max, t[1] + 1);
}

f[l][r][n] = encode(min, max);
return {min, max};
}

int encode(int x, int y) {
return (x << 8) | y;
}

vector<int> decode(int val) {
return {val >> 8, val & 255};
}
};
```

#### Go

```go
var f [30][30][31]int

func earliestAndLatest(n int, firstPlayer int, secondPlayer int) []int {
return dfs(firstPlayer-1, secondPlayer-1, n)
}

func dfs(l, r, n int) []int {
if f[l][r][n] != 0 {
return decode(f[l][r][n])
}
if l+r == n-1 {
f[l][r][n] = encode(1, 1)
return []int{1, 1}
}

min, max := 1<<30, -1<<31
m := n >> 1

for i := 0; i < (1 << m); i++ {
win := make([]bool, n)
for j := 0; j < m; j++ {
if (i>>j)&1 == 1 {
win[j] = true
} else {
win[n-1-j] = true
}
}
if n&1 == 1 {
win[m] = true
}
win[n-1-l] = false
win[n-1-r] = false
win[l] = true
win[r] = true

a, b, c := 0, 0, 0
for j := 0; j < n; j++ {
if j == l {
a = c
}
if j == r {
b = c
}
if win[j] {
c++
}
}

t := dfs(a, b, c)
if t[0]+1 < min {
min = t[0] + 1
}
if t[1]+1 > max {
max = t[1] + 1
}
}

f[l][r][n] = encode(min, max)
return []int{min, max}
}

func encode(x, y int) int {
return (x << 8) | y
}

func decode(val int) []int {
return []int{val >> 8, val & 255}
}
```

#### TypeScript

```ts
function earliestAndLatest(n: number, firstPlayer: number, secondPlayer: number): number[] {
return dfs(firstPlayer - 1, secondPlayer - 1, n);
}

const f: number[][][] = Array.from({ length: 30 }, () =>
Array.from({ length: 30 }, () => Array(31).fill(0)),
);

function dfs(l: number, r: number, n: number): number[] {
if (f[l][r][n] !== 0) {
return decode(f[l][r][n]);
}
if (l + r === n - 1) {
f[l][r][n] = encode(1, 1);
return [1, 1];
}

let min = Number.MAX_SAFE_INTEGER;
let max = Number.MIN_SAFE_INTEGER;
const m = n >> 1;

for (let i = 0; i < 1 << m; i++) {
const win: boolean[] = Array(n).fill(false);
for (let j = 0; j < m; j++) {
if ((i >> j) & 1) {
win[j] = true;
} else {
win[n - 1 - j] = true;
}
}

if (n & 1) {
win[m] = true;
}

win[n - 1 - l] = false;
win[n - 1 - r] = false;
win[l] = true;
win[r] = true;

let a = 0,
b = 0,
c = 0;
for (let j = 0; j < n; j++) {
if (j === l) a = c;
if (j === r) b = c;
if (win[j]) c++;
}

const t = dfs(a, b, c);
min = Math.min(min, t[0] + 1);
max = Math.max(max, t[1] + 1);
}

f[l][r][n] = encode(min, max);
return [min, max];
}

function encode(x: number, y: number): number {
return (x << 8) | y;
}

function decode(val: number): number[] {
return [val >> 8, val & 255];
}
```

<!-- tabs:end -->
Expand Down
Loading