比赛配对问题 | 豆包MarsCode AI刷题
有趣的问题,其实并不需要模拟,用数学的方式思考下可以在O1内解决
问题描述
小R正在组织一个比赛,比赛中有 支队伍参与。比赛遵循以下独特规则:
- 规则 1:如果当前队伍数为 偶数,那么每两支队伍配对,总共进行 场比赛,且产生 支队伍进入下一轮。
- 规则 2:如果当前队伍数为 奇数,那么必须给单独留空的队伍安排一个轮空资格,其余的队伍配对。总共进行 场比赛,且产生 支队伍进入下一轮。
小R想知道在整个比赛过程中需要进行的配对次数,直到只剩下一支获胜队伍为止。
解法 1:逐轮模拟
核心逻辑
在逐轮模拟中:
- 每次根据队伍数量的奇偶性计算出当前需要进行的比赛场次。
- 更新下一轮的队伍数量。
- 重复这一过程,直到只剩下一支队伍。
Go代码实现
package main
import "fmt"
func solution(n int) int {
matches := 0
for n > 1 {
if n%2 == 0 {
// 偶数场次
matches += n / 2
n /= 2
} else {
// 奇数场次
matches += (n - 1) / 2
n = (n - 1) / 2 + 1
}
}
return matches
}
func main() {
// 测试用例
fmt.Println(solution(7) == 6)
fmt.Println(solution(14) == 13)
fmt.Println(solution(1) == 0)
}
Python代码实现
def solution(n: int) -> int:
cnt = 0 # 记录总比赛次数
while n > 1:
cnt += n // 2 # 计算当前轮比赛场次
n = (n // 2) + (n % 2) # 更新剩余队伍数
return cnt
if __name__ == "__main__":
# 测试用例
print(solution(7) == 6) # 应输出 True
print(solution(14) == 13) # 应输出 True
print(solution(1) == 0) # 应输出 True
复杂度分析
-
时间复杂度:
- 每一轮队伍数减少一半,最多进行 轮,因此时间复杂度为 。
-
空间复杂度:
- 只需常数个变量记录比赛次数和剩余队伍数,空间复杂度为 。
解法 2:数学推导
推导过程
换个角度来思考,其实重点在于总的匹配次数,而不在于每次除以2进行匹配这个行为,所以可以认为每次只匹配两支队伍,然后淘汰一支队伍,意思就是说一次匹配=一次淘汰
,所以我们只需要计算总的淘汰队伍数就可以了,即最后只剩下一支队伍对应的淘汰数就是n-1
- 每一场比赛都会淘汰一支队伍。
- 支队伍需要进行 场比赛,才能决出唯一的胜者。
因此:
数学代码实现
Go实现
package main
import "fmt"
func solution(n int) int {
return n-1
}
func main() {
fmt.Println(solution(7) == 6)
fmt.Println(solution(14) == 13)
fmt.Println(solution(1) == 0)
}
Python实现
def solution(n: int) -> int:
return n-1
if __name__ == "__main__":
# 测试用例
print(solution(7) == 6) # 应输出 True
print(solution(14) == 13) # 应输出 True
print(solution(1) == 0) # 应输出 True
复杂度分析
-
时间复杂度:
- 数学公式只需一次减法操作,时间复杂度为 。
-
空间复杂度:
- 不需要额外存储,空间复杂度为 。
比较分析
方法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
---|---|---|---|---|
逐轮模拟 | 模拟过程直观,适合扩展其他规则 | 比较次数多,效率略低 | ||
数学推导 | 高效直接,适合计算简单场次问题 | 不适合更复杂的比赛规则问题 |