问题描述
小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
思路
-
理解问题:我们需要计算在比赛中进行的配对次数,直到只剩下一支队伍。
-
数学推导:
- 每次配对后,队伍数量减半(如果是偶数)或减半加一(如果是奇数)。
- 每次配对都会减少一半的队伍(或一半加一),直到只剩下一支队伍。
- 无论队伍数是奇数还是偶数,每一轮配对都会减少一半的队伍,所以总的配对次数等于初始队伍数减一。
-
公式推导:
- 设初始队伍数为
n,每一轮配对后队伍数为n/2或(n-1)/2 + 1。 - 总配对次数为
n - 1。
- 设初始队伍数为
图解
假设初始队伍数为 7:
- 第一轮:7 支队伍,3 场比赛,剩下 8/2 = 9/2 = 4 支队伍。
- 第二轮:4 支队伍,2 场比赛,剩下 ⅓ = 2 支队伍。
- 第三轮:2 支队伍,1 场比赛,剩下 1 支队伍。
总配对次数为 3 + ˜ + 1 = 6。
代码详解
def solution(n: int) -> int:
# 总配对次数等于初始队伍数减一
return n - 1
if __name__ == '__main__':
print(solution(7) == 6)
print(solution(14) == 13)
print(solution(1) == 0)
知识总结
新知识点
-
数学推导:
- 通过数学推导,我们发现每一轮配对都会减少一半的队伍,直到只剩下一支队伍。
- 总配对次数等于初始队伍数减一。
-
逻辑简化:
- 通过观察和推导,我们可以将问题简化为一个简单的数学公式,避免了复杂的递归或循环。
自己的理解
- 数学思维:在解决这类问题时,数学思维非常重要。通过数学推导,我们可以找到问题的本质,从而简化代码实现。
- 逻辑简化:有时候,复杂的问题可以通过简单的数学公式来解决。这种思维方式可以帮助我们更高效地解决问题。
豆包Marscode 体验
这题属于简单题,可以用纯数学方法解决,最后使得代码更简洁,对于新手同学来说,豆包Marscode的思路提供的帮助很大。它详细给出了问题的解析,步骤分析和算法选择,一步一步地将问题转化为数学问题,再将数学问题转化为程序问题,思路很清晰,对于培养算法问题解决能力有很大帮助。
缺点
在让Marscode给出代码提示时,对于这种简单题,Marscode直接秒了,给出了正确答案。虽然给出答案的同时也给出了解析,但是我觉得这“提示”有失偏颇,虽说算法题通常不破不立,但是对于新手而言,更应该在有略微提示的情况下逐步做题,这样更能激发思维和获得成就感