问题描述
小R正在组织一个比赛,比赛中有 n 支队伍参赛。比赛遵循以下独特的赛制:
- 如果当前队伍数为 偶数,那么每支队伍都会与另一支队伍配对。总共进行
n / 2场比赛,且产生n / 2支队伍进入下一轮。 - 如果当前队伍数为 奇数,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行
(n - 1) / 2场比赛,且产生(n - 1) / 2 + 1支队伍进入下一轮。
小R想知道在比赛中进行的配对次数,直到决出唯一的获胜队伍为止。
测试样例
样例1:
输入:
n = 7
输出:6
样例2:
输入:
n = 14
输出:13
样例3:
输入:
n = 1
输出:0
背景介绍
比赛配对问题是一个典型的递归问题,在许多比赛和竞赛中都有类似的赛制。 通过模拟比赛的各个阶段,我们能够掌握如何根据队伍数量的变化进行配对,最终直到决出一个获胜队伍为止。 类似的赛制常常出现在单败淘汰制(Elimination Tournament)中,也被广泛应用于竞技体育、游戏比赛以及其他需要从多个参与者中选出一位胜者的场景。
在这个问题中,小R组织的比赛遵循一种递进的淘汰赛制。 每轮比赛根据当前队伍的数量(奇数或偶数)进行相应的配对。 队伍配对的规则决定了每轮晋级队伍的数量,而每一轮比赛都会减少一半的队伍。 直到最后剩下唯一一支队伍为止,比赛才会结束。 我们的任务是计算从初始的队伍数量开始,每轮进行多少次配对,最终决出唯一获胜队伍所经历的配对总次数。
这个问题的本质是递归过程的模拟,类似于比赛的“二分法”进程:每一轮将队伍数目减半(或者将队伍数目减去一个并且再减半),直到最终剩下一个队伍。
解题思路
- 理解问题的规则 :
- 当队伍数为 偶数 时,每一场比赛会有两支队伍进行配对,所以总共有
n / 2场比赛。 - 当队伍数为 奇数 时,其中一支队伍轮空,剩余的队伍进行配对,所以总共进行
(n - 1) / 2场比赛,且会有一支队伍自动晋级,总共有(n - 1) / 2 + 1支队伍进入下一轮。
- 当队伍数为 偶数 时,每一场比赛会有两支队伍进行配对,所以总共有
- 递归过程的分析 : 每一轮比赛都会减少一定数量的队伍。 可以通过递归的方式来模拟每一轮的比赛:
- 递归终止条件 :当队伍数目变为 1 时,表示比赛结束,递归停止。
- 递归过程 :每一轮比赛后,队伍数目减少,并且进行的配对次数累加。
- 计算总配对次数 :
对于每一轮:
- 如果当前队伍数为偶数,进行
n / 2场比赛。 - 如果当前队伍数为奇数,进行
(n - 1) / 2场比赛,并且有一支队伍轮空晋级。 每一轮的配对次数会累积到一个总数中,直到队伍数减少为 1 为止。
- 如果当前队伍数为偶数,进行
- 递归实现 : 使用递归函数来模拟每一轮比赛的配对过程。 在每轮中,计算当前的配对次数,递归处理剩下的队伍数。 最终,返回总的配对次数。
代码参考
def solution(n: int) -> int:
total_matches = 0
while n > 1:
if n % 2 == 0: # 如果是偶数队伍
total_matches += n // 2
n //= 2
else: # 如果是奇数队伍
total_matches += (n - 1) // 2
n = (n - 1) // 2 + 1
return total_matches