问题描述
小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
MarsCode代码提示
问题理解
你需要计算在比赛中进行的配对次数,直到决出唯一的获胜队伍为止。比赛遵循以下规则:
- 如果当前队伍数为偶数,每支队伍都会与另一支队伍配对,进行
n / 2场比赛,产生n / 2支队伍进入下一轮。 - 如果当前队伍数为奇数,随机轮空并晋级一支队伍,其余的队伍配对,进行
(n - 1) / 2场比赛,产生(n - 1) / 2 + 1支队伍进入下一轮。
数据结构选择
这个问题不需要复杂的数据结构,只需要一个整数来表示当前的队伍数。
算法步骤
-
边界条件:
- 如果当前队伍数为
1,则不需要进行任何配对,直接返回0。
- 如果当前队伍数为
-
配对次数计算:
- 如果当前队伍数为偶数,计算当前轮的配对次数为
n // 2,并且下一轮的队伍数为n // 2。 - 如果当前队伍数为奇数,计算当前轮的配对次数为
(n - 1) // 2,并且下一轮的队伍数为(n - 1) // 2 + 1。
- 如果当前队伍数为偶数,计算当前轮的配对次数为
-
递归调用:
- 递归计算下一轮的配对次数,直到队伍数为
1。
- 递归计算下一轮的配对次数,直到队伍数为
总结
- 使用递归方法来计算每一轮的配对次数。
- 确保递归调用的参数正确,即根据当前队伍数是奇数还是偶数来选择正确的下一轮队伍数。
- 确保递归终止条件是正确的,即当队伍数为
1时返回0。
def solution(n: int) -> int:
# 边界条件:如果只剩下一个队伍,不需要进行任何配对
if n == 1:
return 0
# 计算当前轮的配对次数
if n % 2 == 0:
pairs = n // 2
next_round_teams = n // 2 # 提示:偶数队伍时,下一轮的队伍数
else:
pairs = (n - 1) // 2
next_round_teams = (n - 1) // 2 + 1 # 提示:奇数队伍时,下一轮的队伍数
# 递归计算下一轮的配对次数
return pairs + solution(next_round_teams) # 提示:使用正确的下一轮队伍数
if __name__ == '__main__':
print(solution(7) == 6)
print(solution(14) == 13)
print(solution(1) == 0)
知识点总结
-
递归(Recursion) :
- 递归是解决这个问题的核心方法。通过递归调用,我们可以逐步减少队伍数,直到只剩下一个队伍为止。
- 递归函数需要有明确的终止条件,即当队伍数为
1时返回0。
-
条件判断(Conditional Statements) :
- 使用
if-else语句来判断当前队伍数是奇数还是偶数,并根据判断结果计算当前轮的配对次数和下一轮的队伍数。
- 使用
-
整数除法和取模运算(Integer Division and Modulo Operation) :
- 使用
//进行整数除法,计算当前轮的配对次数和下一轮的队伍数。
- 使用
-
- 使用
%进行取模运算,判断当前队伍数是奇数还是偶数。
- 使用
-
函数定义和调用(Function Definition and Call) :
- 定义一个函数
solution(n)来计算配对次数。 - 在函数内部调用自身来实现递归。
- 定义一个函数
-
边界条件处理(Edge Case Handling) :
- 处理边界条件,即当队伍数为
1时,直接返回0,因为不需要进行任何配对。
- 处理边界条件,即当队伍数为