20.比赛配对问题,21 环形数组中的最大贡献值 题解| 豆包MarsCode AI刷题

112 阅读4分钟

20.比赛配对问题 题目解析

问题描述

小R组织了一场比赛,有 nn 支队伍参赛,遵循以下规则:

  1. 如果当前队伍数 n 是偶数,所有队伍两两配对,总共 n/2 场比赛,剩下 n/2 支队伍晋级。
  2. 如果当前队伍数 n 是奇数,随机轮空一支队伍晋级,其余队伍配对,总共 (n−1)/2 场比赛,剩下 (n−1)/2+1 支队伍晋级。
  3. 比赛持续进行,直到决出唯一获胜队伍。

目标是计算比赛总共进行了多少场配对比赛。


解题思路

规则分析

  1. 每轮比赛的配对数由当前队伍数 n 决定:
    • 如果 n 是偶数,配对数为 n/2。
    • 如果 n是奇数,配对数为 (n−1)/2。
  2. 无论队伍是奇数还是偶数,下一轮的队伍数总是 n//2 或 n//2+1,随着比赛轮次的增加,队伍数逐渐减少。
  3. 比赛会持续进行,直到只剩下一支队伍。

算法设计

  • 用一个变量 matches 累加配对次数。
  • 当队伍数 n>1 时,根据奇偶性分别计算配对数和下一轮的队伍数,更新 n。
  • 最后返回总配对次数 matches

时间复杂度

每轮队伍数减半,时间复杂度为 O(log⁡n)。


代码实现

def solution(n: int) -> int:
    matches = 0
    while n > 1:  # 当队伍数大于1时继续比赛
        if n % 2 == 0:  # 偶数情况
            matches += n // 2
            n = n // 2
        else:  # 奇数情况
            matches += (n - 1) // 2
            n = (n - 1) // 2 + 1
    return matches

if __name__ == '__main__':
    # 测试样例
    print(solution(7) == 6)  # True
    print(solution(14) == 13)  # True
    print(solution(1) == 0)  # True

总结

  1. 算法关键:按奇偶性计算每轮配对次数,并更新队伍数直到只剩一支队伍。
  2. 复杂度
    • 时间复杂度:O(log⁡n)(每轮队伍数减半)。
    • 空间复杂度:O(1)(只使用常量变量)。
  3. 适用场景:适合计算任意单淘汰赛制下的总比赛场次,高效简洁。

21 环形数组中的最大贡献值 题目解析

问题描述

小S拥有一个长度为 n 的环形数组 a,要求在所有可能的下标对 (i,j)中,找到贡献值公式:

image.png dist(i,j) 是环形数组中 i和 j 的最短距离,计算公式为: image.png

环形数组特点

  1. 相邻特性:数组首尾相接,即 a[0] 与 a[n−1]也算相邻。
  2. 距离特性:两点之间的最短距离可能通过正向或逆向路径决定。

目标

遍历所有下标对 (i,j),计算每对的贡献值 f(i,j)),并返回最大值。


解题思路

暴力解法

  1. 遍历所有 (i,j)) 配对,计算对应的贡献值:
    • 两层嵌套循环
      • 外层遍历 i,范围为 0 到 n−1。
      • 内层遍历 j,范围为 i+1 到 n−1。
    • 计算每对的距离 dist(i,j) 和贡献值 f(i,j)。
  2. 使用变量记录当前的最大贡献值。
  3. 返回最大值。

优化点

  • 复杂度:暴力解法的时间复杂度为 O(n^2),适用于小规模 n 的数组。如果 n 较大,需要进一步优化。

代码实现

def solution(n: int, a: list) -> int:
    max_contribution = float('-inf')
    
    # 遍历所有可能的 i, j 配对
    for i in range(n):
        for j in range(i + 1, n):
            # 计算 i 和 j 之间的最短距离
            dist = min(j - i, n - (j - i))
            # 计算贡献值
            contribution = (a[i] + a[j]) * dist
            # 更新最大贡献值
            max_contribution = max(max_contribution, contribution)
    
    return max_contribution

if __name__ == '__main__':
    print(solution(3, [1, 2, 3]) == 5)  # 测试样例1
    print(solution(4, [4, 1, 2, 3]) == 12)  # 测试样例2
    print(solution(5, [1, 5, 3, 7, 2]) == 24)  # 测试样例3

复杂度分析

  • 时间复杂度:两层循环遍历所有 (i,j),复杂度为 O(n^2)。
  • 空间复杂度:只使用常量变量,复杂度为 O(1)。

优化思路

在暴力解法的基础上,可以通过如下方法优化:

  1. 预计算距离矩阵:预先计算每对下标的距离以减少重复计算。
  2. 空间换时间:对贡献值的性质进行分析,减少不必要的比较。

对于较大规模的 n,需要针对性优化以降低时间复杂度。