解题思路
问题理解
小R正在组织一个比赛,比赛中有 n 支队伍参赛。比赛遵循以下独特的赛制:
- 如果当前队伍数为 偶数,那么每支队伍都会与另一支队伍配对。总共进行
n / 2场比赛,且产生n / 2支队伍进入下一轮。 - 如果当前队伍数为 奇数,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行
(n - 1) / 2场比赛,且产生(n - 1) / 2 + 1支队伍进入下一轮。
小R想知道在比赛中进行的配对次数,直到决出唯一的获胜队伍为止。
数据结构选择
在这个问题中,我们不需要复杂的数据结构。我们只需要一个整数变量来记录当前的队伍数 n,以及另一个整数变量来记录配对次数 pairs。
算法步骤
-
初始化:
- 初始化
pairs为 0,表示初始配对次数为 0。 - 初始化
n为输入的队伍数。
- 初始化
-
循环处理每一轮比赛:
-
当
n大于 1 时,继续进行比赛。 -
如果
n为偶数:- 配对次数
pairs增加n / 2。 - 更新
n为n / 2。
- 配对次数
-
如果
n为奇数:- 配对次数
pairs增加(n - 1) / 2。 - 更新
n为(n - 1) / 2 + 1。
- 配对次数
-
-
返回结果:
- 当
n变为 1 时,循环结束,返回pairs作为最终的配对次数。
- 当
详细步骤
-
初始化:
pairs = 0n = 输入的队伍数
-
循环处理每一轮比赛:
-
循环条件:
while n > 1-
偶数情况:
-
如果
n % 2 == 0:pairs += n // 2n = n // 2
-
-
奇数情况:
-
如果
n % 2 != 0:pairs += (n - 1) // 2n = (n - 1) // 2 + 1
-
-
-
-
返回结果:
return pairs
总结
算法复杂度分析
-
时间复杂度:
- 每次循环中,队伍数
n至少减半(偶数情况)或接近减半(奇数情况)。因此,循环的次数大约为log(n)次。 - 每次循环中的操作是常数时间复杂度
O(1)。 - 因此,总的时间复杂度为
O(log(n))。
- 每次循环中,队伍数
-
空间复杂度:
- 只使用了两个整数变量
pairs和n,因此空间复杂度为O(1)。
- 只使用了两个整数变量
代码实现
def solution(n: int) -> int:
# 初始化配对次数
pairs = 0
# 循环直到队伍数变为1
while n > 1:
if n % 2 == 0:
# 队伍数为偶数
pairs += n // 2 # 增加 n / 2 次配对
n = n // 2 # 更新队伍数
else:
# 队伍数为奇数
pairs += (n - 1) // 2 # 增加 (n -
1) / 2 次配对
n = (n - 1) // 2 + 1 # 更新队伍数
return pairs
if name == 'main':
print(solution(7) == 6)
print(solution(14) == 13)
print(solution(1) == 0)
代码解释
- 初始化:
pairs = 0和n = 输入的队伍数。 - 循环:
while n > 1,根据n的奇偶性更新pairs和n。 - 返回:
return pairs,返回最终的配对次数。
测试样例
-
样例1:
n = 7- 初始
pairs = 0,n = 7 - 第一轮:
pairs += (7 - 1) // 2 = 3,n = (7 - 1) // 2 + 1 = 4 - 第二轮:
pairs += 4 // 2 = 2,n = 4 // 2 = 2 - 第三轮:
pairs += 2 // 2 = 1,n = 2 // 2 = 1 - 最终
pairs = 6
- 初始
-
样例2:
n = 14- 初始
pairs = 0,n = 14 - 第一轮:
pairs += 14 // 2 = 7,n = 14 // 2 = 7 - 第二轮:
pairs += (7 - 1) // 2 = 3,n = (7 - 1) // 2 + 1 = 4 - 第三轮:
pairs += 4 // 2 = 2,n = 4 // 2 = 2 - 第四轮:
pairs += 2 // 2 = 1,n = 2 // 2 = 1 - 最终
pairs = 13
- 初始
-
样例3:
n = 1- 初始
pairs = 0,n = 1 - 直接返回
pairs = 0
- 初始
总结
通过上述分析和代码实现,我们可以看到,这个问题可以通过简单的循环和条件判断来解决。关键在于理解每轮比赛的规则,并正确更新队伍数和配对次数。时间复杂度为 O(log(n)),空间复杂度为 O(1),是一个高效且简洁的解决方案。