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

58 阅读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

算法思路

这个问题实际上是一个关于递归和数学的问题。我们需要计算在每一轮比赛中进行的配对次数,直到只剩下一支队伍。我们可以观察到,每一轮比赛后,队伍的数量会减少一半(如果队伍数为偶数)或者减少一半再加一(如果队伍数为奇数)。这个过程会一直持续,直到只剩下一支队伍。

构建一个数组num_per_round[ ]存放每轮比赛结束后剩余的人数

如果剩余人数为1,无法继续配对,比赛结束

num_per_round[0] = n

num_per_round[1] = int(num_per_round[0]) - int(num_per_round[0] / 2)

num_per_round[2] = int(num_per_round[1]) - int(num_per_round[1] / 2)

……

最后遍历数组,用第i轮的比赛人数与第i - 1轮的比赛人数相减即为这一轮的比赛轮次,累加即可得到最终结果

算法执行流程

样例1:n = 7
第 1 轮比赛后剩下 4 支队伍,进行了 3 场比赛
第 2 轮比赛后剩下 2 支队伍,进行了 2 场比赛
第 3 轮比赛后剩下 1 支队伍,进行了 1 场比赛
总共进行了 6 场比赛

样例2: n = 14
第 1 轮比赛后剩下 7 支队伍,进行了 7 场比赛
第 2 轮比赛后剩下 4 支队伍,进行了 3 场比赛
第 3 轮比赛后剩下 2 支队伍,进行了 2 场比赛
第 4 轮比赛后剩下 1 支队伍,进行了 1 场比赛
总共进行了 13 场比赛

样例3: n = 1
总共进行了 0 场比赛

Solution

 class Main {
     public static int solution(int n) {
         int[] num_per_round = new int[100];
 ​
         num_per_round[0] = n;
 ​
         for (int i = 1; i < 100; i++) {
             if (num_per_round[i - 1] == 1) {
                 break;
             }
             num_per_round[i] = (num_per_round[i - 1] % 2 == 0) ? (num_per_round[i - 1] / 2)
                     : (num_per_round[i - 1] / 2 + 1);
         }
 ​
         int res = 0;
 ​
         for (int j = 1; j < 100; j++) {
             if (num_per_round[j - 1] == 1) {
                 break;
             }
             res += num_per_round[j - 1] - num_per_round[j];
         }
 ​
         return res;
     }
 ​
     public static void main(String[] args) {
         System.out.println(solution(7));
         System.out.println(solution(14));
         System.out.println(solution(1));
     }
 }
// 递归法
public class Solution {
    public int numberOfMatches(int n) {
        // 如果只有一支队伍,不需要比赛
        if (n <= 1) {
            return 0;
        }
        // 如果队伍数为偶数,每轮比赛后队伍数减半
        // 如果队伍数为奇数,每轮比赛后队伍数减半再加一
        // 因此,每轮比赛的配对次数为 n/2 (向下取整)
        return (n / 2) + numberOfMatches(n / 2 + n % 2);
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.numberOfMatches(7)); // 输出:6
        System.out.println(solution.numberOfMatches(14)); // 输出:13
        System.out.println(solution.numberOfMatches(1)); // 输出:0
    }
}