一、题目分析
有 n 支队伍参赛,赛制根据队伍数量的奇偶性有所不同:
- 当队伍数为偶数时,每两支队伍配对进行比赛,总共进行
n / 2场比赛,且比赛结束后会产生n / 2支队伍进入下一轮。 - 当队伍数为奇数时,会随机让一支队伍轮空直接晋级下一轮,其余队伍两两配对进行比赛。此时总共进行
(n - 1) / 2场比赛,比赛结束后会产生(n - 1) / 2 + 1支队伍进入下一轮。
题目要求计算在这样的赛制下,直到决出唯一的获胜队伍为止,整个比赛过程中进行的配对次数。
这个问题的关键在于根据队伍数量的奇偶性准确模拟每一轮比赛的队伍配对和晋级情况,并正确累计每一轮的配对次数。
二、题解思路
(一)整体思路
通过循环不断模拟比赛的每一轮,在每一轮中根据当前队伍数量 n 的奇偶性,按照给定的赛制规则进行相应的操作,包括计算本轮的配对次数、确定进入下一轮的队伍数量,同时累计每一轮的配对次数。循环持续进行,直到决出唯一的获胜队伍(即 n 变为 1),最后返回累计的配对次数作为最终答案。
(二)代码实现细节
1. 变量初始化
在 solution 方法中,首先定义了一个变量 pairings,用于累计比赛过程中的配对次数,将其初始化为 0。这个变量会在后续模拟每一轮比赛时,根据实际情况不断累加本轮的配对次数。
2. 循环模拟比赛轮次
使用 while 循环来模拟比赛的每一轮,循环的条件是 n > 1。因为当队伍数为 1 时,就意味着已经决出了唯一的获胜队伍,比赛过程结束,不需要再进行后续的模拟了。
-
队伍数为偶数的情况(
n % 2 == 0):- 当判断当前队伍数
n为偶数时,按照赛制,每两支队伍配对进行比赛,总共进行n / 2场比赛,这也就意味着有n / 2次配对操作。所以首先将n除以2,得到进入下一轮的队伍数量,这一步模拟了偶数队伍配对后晋级的情况。例如,如果当前有14支队伍(偶数),那么经过这一轮比赛后,会有14 / 2 = 7支队伍进入下一轮。 - 然后将
n / 2累加到pairings中,实现了对本轮配对次数的累计。继续以上述例子,如果当前是14支队伍的轮次,那么本轮的配对次数就是14 / 2 = 7,pairings就会增加7。
- 当判断当前队伍数
-
队伍数为奇数的情况(
n % 2!= 0):- 当判断当前队伍数
n为奇数时,按照赛制,会随机有一支队伍轮空直接晋级下一轮,其余队伍两两配对进行比赛。首先计算本轮比赛产生的晋级队伍数量,通过(n - 1) / 2 + 1来得到,这里(n - 1) / 2表示配对比赛的队伍对数,再加上1就是包括轮空晋级队伍在内进入下一轮的队伍总数。例如,如果当前有7支队伍(奇数),那么经过这一轮比赛后,会有(7 - 1) / 2 + 1 = 4支队伍进入下一轮。 - 接着计算本轮的配对次数,即
(n - 1) / 2。因为除了轮空的那支队伍,其余n - 1支队伍两两配对,所以配对次数就是(n - 1) / 2。例如,对于7支队伍的情况,本轮配对次数就是(7 - 1) / 2 = 3。然后将这个配对次数累加到pairings中。 - 最后将计算得到的进入下一轮的队伍数量(即
(n - 1) / 2 + 1)赋值给n,以便在下一轮循环中继续根据新的队伍数量进行模拟操作。
- 当判断当前队伍数
3. 返回结果
当 while 循环结束后,也就是经过多轮比赛,最终决出唯一的获胜队伍(n 变为 1)时,此时 pairings 变量中存储的就是整个比赛过程中从最初的 n 支队伍开始,直到决出冠军为止所进行的所有轮次的配对次数总和。最后将 pairings 返回,作为本题的最终答案。
通过这样的代码实现,能够准确地根据题目给定的赛制模拟比赛过程,并正确计算出整个比赛过程中的配对次数。
代码
public static int solution(int n) {
int pairings = 0;
while (n > 1) {
if (n % 2 == 0) {
// 队伍数为偶数
n /= 2;
pairings += n;
} else {
// 队伍数为奇数
int temp = (n - 1) / 2 + 1;//也就是产生多少支队伍进入下一场
pairings += (n - 1) / 2;
n = temp;
}
}
return pairings;
}