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

125 阅读4分钟

在这个问题中,我们需要计算一个比赛中进行的总配对次数,直到最终决出一支获胜队伍。比赛规则较为特殊,需要分别考虑奇数队伍偶数队伍的情况。这类问题适合用循环递归来实现,本文将详细解析解决方案和实现步骤。


问题描述

  1. 规则

    • 如果当前队伍数为偶数,每两支队伍配对比赛,总共有 n/2n / 2n/2 场比赛,晋级的队伍数为 n/2n / 2n/2。
    • 如果当前队伍数为奇数,则随机选一支队伍轮空自动晋级,剩余的队伍配对,总共有 (n−1)/2(n - 1) / 2(n−1)/2 场比赛,晋级的队伍数为 (n−1)/2+1(n - 1) / 2 + 1(n−1)/2+1。
  2. 目标

    • 计算总共进行了多少次配对,直到决出唯一的获胜队伍。
  3. 测试样例

    • 输入 n=7n = 7n=7,输出 6。
    • 输入 n=14n = 14n=14,输出 13。
    • 输入 n=1n = 1n=1,输出 0。

解题思路

  1. 核心思想

    • 比赛结束的条件是队伍数降到 1。
    • 每轮比赛中,依据队伍数的奇偶性,计算当前轮的配对次数,并更新下一轮队伍的数量。
    • 将每轮的配对次数累计起来,得到最终的总配对次数。
  2. 两种情况

    • 偶数:
      当前队伍数 nnn 为偶数时,配对次数为 n/2n / 2n/2。比赛结束后,晋级的队伍数也为 n/2n / 2n/2。
    • 奇数:
      当前队伍数 nnn 为奇数时,配对次数为 (n−1)/2(n - 1) / 2(n−1)/2。剩下的一支队伍轮空直接晋级,因此下一轮的队伍总数为 (n−1)/2+1(n - 1) / 2 + 1(n−1)/2+1。
  3. 边界条件

    • 当队伍数为 1 时,比赛结束,配对次数为 0。

代码实现

以下是 Java 的完整实现代码:

java
复制代码
class Main {
    public static int solution(int n) {
        int matches = 0; // 记录配对总次数
        while (n > 1) {  // 只要队伍数大于1,就继续比赛
            if (n % 2 == 0) { // 偶数情况
                matches += n / 2;
                n /= 2;
            } else { // 奇数情况
                matches += (n - 1) / 2;
                n = (n - 1) / 2 + 1;
            }
        }
        return matches;
    }

    public static void main(String[] args) {
        System.out.println(solution(7) == 6);  // 测试样例1
        System.out.println(solution(14) == 13); // 测试样例2
        System.out.println(solution(1) == 0);  // 测试样例3
    }
}

代码解析

  1. 初始化变量

    • matches 用于记录总配对次数。
    • 每轮比赛后更新队伍数 n
  2. 循环逻辑

    • 当队伍数大于 1 时,根据队伍的奇偶性分别处理:

      • 偶数:直接进行 n/2n / 2n/2 场比赛,并将队伍数减半。
      • 奇数:进行 (n−1)/2(n - 1) / 2(n−1)/2 场比赛,并额外轮空一支队伍晋级。
  3. 停止条件

    • 当队伍数减少到 1 时,循环结束,返回累计的 matches

复杂度分析

  1. 时间复杂度

    • 每轮比赛队伍数减少约一半,因此循环次数为 O(log⁡n)O(\log n)O(logn)。
    • 每轮计算和更新操作为 O(1)O(1)O(1),总体复杂度为 O(log⁡n)O(\log n)O(logn)。
  2. 空间复杂度

    • 使用了常量级变量 O(1)O(1)O(1),不需要额外的空间。

测试样例分析

  1. 输入 n=7n = 7n=7:

    • 第 1 轮:7→67 \rightarrow 67→6(1 轮空),3 场比赛。
    • 第 2 轮:4→24 \rightarrow 24→2,2 场比赛。
    • 第 3 轮:2→12 \rightarrow 12→1,1 场比赛。
    • 总配对次数:3+2+1=63 + 2 + 1 = 63+2+1=6。
  2. 输入 n=14n = 14n=14:

    • 第 1 轮:14→714 \rightarrow 714→7,7 场比赛。
    • 第 2 轮:7→47 \rightarrow 47→4(1 轮空),3 场比赛。
    • 第 3 轮:4→24 \rightarrow 24→2,2 场比赛。
    • 第 4 轮:2→12 \rightarrow 12→1,1 场比赛。
    • 总配对次数:7+3+2+1=137 + 3 + 2 + 1 = 137+3+2+1=13。
  3. 输入 n=1n = 1n=1:

    • 队伍数已经为 1,无需比赛,配对次数为 0。

总结

该问题是一个经典的循环递减问题,通过对奇偶情况的分类讨论,逐步减少队伍数并累计配对次数。核心逻辑简单,但需要注意边界条件和对奇数情况的正确处理。

这类问题的解题思路在实际竞赛中具有普遍意义,常见于队列处理、分治算法等场景。通过分析递减规律,可以有效降低时间复杂度,并找到清晰的解决方案。

4o