20 比赛配对问题 题解 | 豆包MarsCode AI刷题

160 阅读3分钟

问题描述

小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.比赛规则

小R的比赛有以下特点:

1.每轮比赛的队伍总数 n 决定比赛场次:

  • 如果 n 为 偶数,所有队伍两两配对,进行 n/2 场比赛,获胜的 n/2 支队伍进入下一轮,
  • 如果 n 为 奇数,随机轮空一支队伍直接晋级,其余队伍两两配对,进行(n - 1)/2 场比 赛。进入下一轮的队伍总数为(n -1)/2+1; 2.比赛持续进行,队伍总数逐轮减少,直到仅剩一支队伍为止。

2.目标

计算在整个比赛过程中,总共进行了多少场配对比赛

解题思路:

1.每轮比赛的计算公式

每轮的比赛场次是当前队伍数 n 的整除结果:

  • 如果 n 是偶数,比赛场次为 n/2;
  • 如果 n 是奇数,比赛场次为(n-1)/2(等价于n//2)

同时,下一轮的队伍数更新规则为:n=n//2+n%2

  • n//2 表示配对比赛的获胜队伍数;
  • n%2 表示当 n 为奇数时轮空直接晋级的队伍。

2.终止条件

比赛会持续进行,直到几=1(剩下一支队伍时结束)

3.总比赛场次累加

我们用一个变量 count来累计每轮的比赛场次,直到比赛结束

4.简化观寨

在整个比赛中,每次减少的队伍数量等于比赛场次,而队伍总数几会逐步减少到 1。因此

  • 比赛场次的总和等于原始队伍数 n 减去1(最终剩余的唯一队伍)。

解题步骤

1.理解题目规则

每轮比赛规则可直接归纳为:配对数 =n//2,并更新队伍数为 n= n//2 +n%2。

2.初始化变量

设 count 为总配对次数,初始值为 0。

3.模拟比赛过程

  • 在循环中,计算当前轮配对数,累加到count;
  • 更新队伍数 n,模拟进入下一轮;
  • 当 n ==1 时,跳出循环。

4.返回结果

输出 count,即比赛中进行的总配对次数。

代码实现:

def solution(n: int) -> int:
    # 初始化配对次数
    count = 0
    
    # 模拟比赛过程
    while n > 1:
        count += n // 2  # 当前轮比赛场次
        n = n // 2 + n % 2  # 更新剩余队伍数
    
    return count

复杂度分析:

1.时间复杂度:O(log n)

每轮队伍数减少到原来的一半,最多需要 log n 轮。

2.空间复杂度:O(1)

仅使用常量变量 count 和n。

直观公式化观察:

对于任意队伍数 ,总比赛场次等于所有被淘汰队伍数:

  • 比赛淘汰n-1支队伍,剩余1支获胜;
  • 所以总比赛场次是n-1。