比赛配对问题分析 | 豆包MarsCode AI刷题

131 阅读5分钟

题目解析与思路

小R组织的比赛具有独特的赛制,每轮比赛根据队伍数量的奇偶性来决定比赛的场次和晋级的队伍数。对于每轮比赛,如果当前队伍数是偶数,每支队伍都能与另一支队伍配对,进行比赛;如果当前队伍数是奇数,那么会随机轮空一支队伍,其余队伍进行配对。这一赛制最终会决出一个唯一的胜者。

我们需要计算从比赛开始到决出最终获胜队伍为止,所有的配对次数。换句话说,我们要统计每轮比赛中有多少场比赛进行,直到剩下最后一支队伍。

关键问题分析

对于这个问题,我们可以将其转化为一个模拟过程。每轮比赛后,队伍数会减少一半(或接近一半),直到最后剩下一个队伍为止。因此,可以通过模拟每一轮比赛的过程来求解。特别地,我们可以根据队伍数的奇偶性来决定比赛规则,从而不断地更新队伍数并统计配对次数。

具体步骤

  1. 判断队伍数的奇偶性

    • 如果队伍数为偶数,那么每两支队伍配对一次,总共进行 ( n / 2 ) 场比赛。
    • 如果队伍数为奇数,那么有一支队伍轮空,剩余的 ( n-1 ) 支队伍两两配对,总共进行 ( (n - 1) / 2 ) 场比赛。
    • 每轮结束后,队伍数将减半,或者(当队伍数为奇数时)减去轮空的队伍后,再加上一支轮空的队伍晋级。
  2. 循环进行

    • 重复上述过程,直到队伍数为1为止,此时比赛结束。
  3. 统计配对次数

    • 每轮比赛产生的配对次数都需要累加,直到所有的比赛结束。

代码实现

def solution(n: int) -> int:
    # 初始化配对次数
    pairs = 0
    
    # 当队伍数大于1时,继续配对
    while n > 1:
        if n % 2 == 0:
            # 如果队伍数为偶数,进行 n/2 场比赛
            pairs += n // 2
            n //= 2
        else:
            # 如果队伍数为奇数,进行 (n-1)/2 场比赛,并有一支队伍轮空
            pairs += (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)

代码分析

  1. 初始化配对次数pairs = 0用于存储比赛中的总配对次数。

  2. 模拟比赛过程

    • 使用while n > 1:循环,直到剩下最后一支队伍。每轮比赛结束后,队伍数减少。
    • 判断队伍数的奇偶性,分别处理:
      • 如果队伍数为偶数,则进行n // 2场比赛,队伍数更新为n // 2
      • 如果队伍数为奇数,则进行(n - 1) // 2场比赛,一支队伍轮空,队伍数更新为(n - 1) // 2 + 1
  3. 返回总配对次数:最终返回pairs,即所有比赛中的配对次数。

测试与验证

  • solution(7):输入7支队伍,比赛过程如下:
    • 第1轮:有7支队伍,其中6支队伍进行配对,产生3场比赛,剩下1支队伍轮空,晋级队伍数为4(3场比赛 + 1轮空)。
    • 第2轮:有4支队伍,进行2场比赛,剩下2支队伍。
    • 第3轮:有2支队伍,进行1场比赛,最终决出1支队伍。
    • 总配对次数为3 + 2 + 1 = 6。
  • solution(14):输入14支队伍,比赛过程如下:
    • 第1轮:有14支队伍,进行7场比赛,晋级队伍数为7。
    • 第2轮:有7支队伍,进行3场比赛,剩下1支队伍轮空,晋级队伍数为4(3场比赛 + 1轮空)。
    • 第3轮:有4支队伍,进行2场比赛,晋级队伍数为2。
    • 第4轮:有2支队伍,进行1场比赛,最终决出1支队伍。
    • 总配对次数为7 + 3 + 2 + 1 = 13。

学习心得与建议

  1. 细化问题分析

    • 在解决这类问题时,首先要理解每个规则对数据的影响。特别是要注意队伍数的奇偶性,正确地推导每轮比赛的场次和队伍数更新方法。
  2. 模拟与递归思维

    • 这类问题本质上是一个逐步简化问题的过程。通过模拟每一轮比赛的过程,我们能够清晰地得到最终的答案。在编写代码时,逐步缩小问题规模,直到达到最终状态,是解决此类问题的关键。
  3. 时间复杂度

    • 每轮比赛后,队伍数减少一半,因此最多进行log n轮比赛。每轮的操作复杂度为常数,因此总的时间复杂度为O(log n),是一个非常高效的解决方案。
  4. 代码简洁性与可读性

    • 在实现中,代码简洁且直观。通过循环模拟每一轮比赛,判断奇偶性后分别处理,对于入门同学来说,这样的解法易于理解且实现简单。
  5. 扩展思路

    • 如果队伍数非常庞大,可能需要考虑更复杂的优化方法,比如动态规划或其他算法。尽管当前的模拟方法在时间复杂度上已足够优秀,但在特定场景下(如超大规模数据),可能会涉及到更加优化的解法。

总结

通过这道问题,我们不仅复习了基本的模拟和迭代技巧,还加深了对问题逐步简化、逐层递归的理解。在解题过程中,掌握每轮比赛的规则,并根据队伍数的奇偶性处理配对情况,能够高效解决这类问题。希望入门的同学能够通过这道题提高自己对算法模拟过程的理解,并能够在以后的题目中灵活运用。