1688. 比赛中的配对次数

137 阅读2分钟

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。

题目描述

给你一个整数 n ,表示比赛中的队伍数。比赛遵循一种独特的赛制:

如果当前队伍数是 偶数 ,那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛,且产生 n / 2 支队伍进入下一轮。 如果当前队伍数为 奇数 ,那么将会随机轮空并晋级一支队伍,其余的队伍配对。总共进行 (n - 1) / 2 场比赛,且产生 (n - 1) / 2 + 1 支队伍进入下一轮。 返回在比赛中进行的配对次数,直到决出获胜队伍为止。

示例 1:

输入:n = 7
输出:6
解释:比赛详情:
- 第 1 轮:队伍数 = 7 ,配对次数 = 3 ,4 支队伍晋级。
- 第 2 轮:队伍数 = 4 ,配对次数 = 2 ,2 支队伍晋级。
- 第 3 轮:队伍数 = 2 ,配对次数 = 1 ,决出 1 支获胜队伍。
总配对次数 = 3 + 2 + 1 = 6

思路分析

最简单的就是模拟的方式,按照他的方式进行配对与晋级。偶数时减半,并加上这部分值,奇数时减半+1,因为有一个人轮空,所以7人比赛会和8人比赛一个结果,但是此时比赛数只有3次,因此需要ret += n - 1

int numberOfMatches(int n) {
        int ret = 0;
        while(n > 1){
            if (n % 2 == 0){
                // 偶数
                n = n / 2;
                ret += n;
            }else{
                // 奇数
                n = n / 2 + 1;
                ret += (n - 1);
            }
        }
        return ret;
    }

截屏2022-01-25 下午11.51.51.png

但理论上应该还有数学方法可以优化,至少我们发现,每次偶数时ret增加的值都是它本身/2,每次奇数时增加的值也都是他➗2【但是n整体其实是➗2+1的】,因此这个思路没法正向算,我们可以反过来想:每次比赛淘汰一个选手,总共淘汰n-1个选手,因此总共有n-1次比赛。

int numberOfMatches(int n) {
        return n -1;
    }

截屏2022-01-26 上午12.03.23.png

难不成还可以继续优化?

查看了前100%的题解发现答案和我的提交一样。