The Earliest and Latest Rounds Where Players Compete
update Jun 19, 2021

Basic Idea:
有一种比较巧妙的思路,就是只关注p1 p2 index的变化,因为在他们相遇之前,他们会在所有compete中取胜,于是我们可以根据他们的位置穷举可能出现的下一场的人数分布,从而算出下一场 p1 和 p2 所在的位置。因为最多进行 log2(N)
场,而每次最多尝试 N^2
次,总时间复杂度应该在 O(N^(2logN))
,考虑到N比较小,还是很快的。
Java Code:
class Solution {
public int[] earliestAndLatest(int n, int firstPlayer, int secondPlayer) {
int p1 = Math.min(firstPlayer, secondPlayer);
int p2 = Math.max(firstPlayer, secondPlayer);
// 此时 p1 p2 直接交锋,结束
if (p1 + p2 == n + 1) {
return new int[]{1, 1};
}
if (n < 4) {
return new int[]{2, 2};
}
// 让 p1 p2 更靠左边, 沿中线镜像翻转p1 p2不影响结果
// 1 2 3 4 5 6 7 8 9 10 11 12
// 1 2
// 变成
// 1 2 3 4 5 6 7 8 9 10 11 12
// 1 2
if (p1 - 1 > n - p2) {
int t = n - p1 + 1;
p1 = n - p2 + 1;
p2 = t;
}
int[] ret = new int[]{100, -1};
int nextRoundPlayers = (n + 1) / 2;
// 当 p1 p2 都在中线左侧的时候, 或者p2在中线上
// 1 2 3 4 5 6 7 8 9 10 11 12
// 1 2
// p1左边的12,以及中间的4可能赢又可能输,右边谁留下都不影响,下一局参赛总数不变
if (p2 * 2 <= n + 1) {
for (int i = 0; i < p1; ++i) {
for (int j = 0; j < p2 - p1; ++j) {
int[] next = earliestAndLatest(nextRoundPlayers, i + 1, i + j + 2);
ret[0] = Math.min(ret[0], next[0]);
ret[1] = Math.max(ret[1], next[1]);
}
}
}
// 当 p1 p2 在中线两边
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// | | |
// 1 lp2 l 2 因为之前转换过位置,此处一定p1p2一定偏左
// 6789 一定留两个,p1左边以及p1p2之间不对称的4可能留可能不留
// 而中间6789的长度l随N是奇偶变化, 只需要算出p2沿中心对称的位置lp2即可
else {
int lp2 = n + 1 - p2;
int l = p2 - lp2 - 1;
for (int i = 0; i < p1; ++i) {
for (int j = 0; j < lp2 - p1; ++j) {
int[] next = earliestAndLatest(nextRoundPlayers, i + 1, i + 1 + j + (l + 1) / 2 + 1);
ret[0] = Math.min(ret[0], next[0]);
ret[1] = Math.max(ret[1], next[1]);
}
}
}
ret[0] += 1;
ret[1] += 1;
return ret;
}
}
Last updated