在这个问题中,我们需要计算一个比赛中进行的总配对次数,直到最终决出一支获胜队伍。比赛规则较为特殊,需要分别考虑奇数队伍和偶数队伍的情况。这类问题适合用循环或递归来实现,本文将详细解析解决方案和实现步骤。
问题描述
-
规则:
- 如果当前队伍数为偶数,每两支队伍配对比赛,总共有 n/2n / 2n/2 场比赛,晋级的队伍数为 n/2n / 2n/2。
- 如果当前队伍数为奇数,则随机选一支队伍轮空自动晋级,剩余的队伍配对,总共有 (n−1)/2(n - 1) / 2(n−1)/2 场比赛,晋级的队伍数为 (n−1)/2+1(n - 1) / 2 + 1(n−1)/2+1。
-
目标:
- 计算总共进行了多少次配对,直到决出唯一的获胜队伍。
-
测试样例:
- 输入 n=7n = 7n=7,输出 6。
- 输入 n=14n = 14n=14,输出 13。
- 输入 n=1n = 1n=1,输出 0。
解题思路
-
核心思想:
- 比赛结束的条件是队伍数降到 1。
- 每轮比赛中,依据队伍数的奇偶性,计算当前轮的配对次数,并更新下一轮队伍的数量。
- 将每轮的配对次数累计起来,得到最终的总配对次数。
-
两种情况:
- 偶数:
当前队伍数 nnn 为偶数时,配对次数为 n/2n / 2n/2。比赛结束后,晋级的队伍数也为 n/2n / 2n/2。 - 奇数:
当前队伍数 nnn 为奇数时,配对次数为 (n−1)/2(n - 1) / 2(n−1)/2。剩下的一支队伍轮空直接晋级,因此下一轮的队伍总数为 (n−1)/2+1(n - 1) / 2 + 1(n−1)/2+1。
- 偶数:
-
边界条件:
- 当队伍数为 1 时,比赛结束,配对次数为 0。
代码实现
以下是 Java 的完整实现代码:
java
复制代码
class Main {
public static int solution(int n) {
int matches = 0; // 记录配对总次数
while (n > 1) { // 只要队伍数大于1,就继续比赛
if (n % 2 == 0) { // 偶数情况
matches += n / 2;
n /= 2;
} else { // 奇数情况
matches += (n - 1) / 2;
n = (n - 1) / 2 + 1;
}
}
return matches;
}
public static void main(String[] args) {
System.out.println(solution(7) == 6); // 测试样例1
System.out.println(solution(14) == 13); // 测试样例2
System.out.println(solution(1) == 0); // 测试样例3
}
}
代码解析
-
初始化变量:
matches用于记录总配对次数。- 每轮比赛后更新队伍数
n。
-
循环逻辑:
-
当队伍数大于 1 时,根据队伍的奇偶性分别处理:
- 偶数:直接进行 n/2n / 2n/2 场比赛,并将队伍数减半。
- 奇数:进行 (n−1)/2(n - 1) / 2(n−1)/2 场比赛,并额外轮空一支队伍晋级。
-
-
停止条件:
- 当队伍数减少到 1 时,循环结束,返回累计的
matches。
- 当队伍数减少到 1 时,循环结束,返回累计的
复杂度分析
-
时间复杂度:
- 每轮比赛队伍数减少约一半,因此循环次数为 O(logn)O(\log n)O(logn)。
- 每轮计算和更新操作为 O(1)O(1)O(1),总体复杂度为 O(logn)O(\log n)O(logn)。
-
空间复杂度:
- 使用了常量级变量 O(1)O(1)O(1),不需要额外的空间。
测试样例分析
-
输入 n=7n = 7n=7:
- 第 1 轮:7→67 \rightarrow 67→6(1 轮空),3 场比赛。
- 第 2 轮:4→24 \rightarrow 24→2,2 场比赛。
- 第 3 轮:2→12 \rightarrow 12→1,1 场比赛。
- 总配对次数:3+2+1=63 + 2 + 1 = 63+2+1=6。
-
输入 n=14n = 14n=14:
- 第 1 轮:14→714 \rightarrow 714→7,7 场比赛。
- 第 2 轮:7→47 \rightarrow 47→4(1 轮空),3 场比赛。
- 第 3 轮:4→24 \rightarrow 24→2,2 场比赛。
- 第 4 轮:2→12 \rightarrow 12→1,1 场比赛。
- 总配对次数:7+3+2+1=137 + 3 + 2 + 1 = 137+3+2+1=13。
-
输入 n=1n = 1n=1:
- 队伍数已经为 1,无需比赛,配对次数为 0。
总结
该问题是一个经典的循环递减问题,通过对奇偶情况的分类讨论,逐步减少队伍数并累计配对次数。核心逻辑简单,但需要注意边界条件和对奇数情况的正确处理。
这类问题的解题思路在实际竞赛中具有普遍意义,常见于队列处理、分治算法等场景。通过分析递减规律,可以有效降低时间复杂度,并找到清晰的解决方案。
4o