问题描述
小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
解题思路分析
1. 赛制特点
根据题目描述:
- 偶数队伍时,队伍数减半,配对次数为
n / 2。 - 奇数队伍时,会有一支队伍轮空,配对次数为
(n - 1) / 2,下一轮的队伍数为(n - 1) / 2 + 1。 每轮比赛后队伍数会逐渐减少,因此可以通过模拟这一过程,计算累计的配对次数。
2. 逐轮模拟
比赛进行时,队伍数从 n 逐步减少:
- 如果
n是偶数,每轮比赛会进行n / 2场,晋级n / 2支队伍。 - 如果
n是奇数,先轮空一支队伍,剩余队伍进行(n - 1) / 2场比赛,晋级(n - 1) / 2 + 1支队伍。 - 重复上述过程,直到队伍数为 1,此时比赛结束。
3. 算法设计
使用一个循环模拟比赛过程:
- 每轮根据队伍数是奇数还是偶数计算配对次数。
- 累加每轮的配对次数,直到队伍数为 1。
4. 边界条件
- 当
n = 1时,没有比赛,配对次数为 0。 - 当
n很大时,通过逐轮减半的方式,算法能够高效完成计算。
代码实现
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
知识点总结
1. 奇偶数分类讨论
- 偶数的特点:可以直接成对分组。
- 奇数的特点:必须有一支队伍轮空,这种处理方式使得队伍数逐渐减少且问题有序。
2. 循环模拟的有效性
每轮比赛会将队伍数减少一半(或接近一半),循环的迭代次数为 。这一性质使得模拟过程的时间复杂度为 ,可以高效处理非常大的 n。
思考与优化
1. 时间复杂度分析
由于每轮队伍数减少一半,算法的时间复杂度为 。
2. 边界条件处理
n = 1:没有比赛,直接返回 0。n很大时:算法依然高效,可以处理百万级别的输入。
3. 递归实现
除了循环实现,还可以使用递归:
def solution(n: int) -> int:
if n <= 1:
return 0
if n % 2 == 0:
return n // 2 + solution(n // 2)
else:
return (n - 1) // 2 + solution((n - 1) // 2 + 1)
递归和循环实现的核心思想相同,均基于逐轮减少队伍数。