题目解析 | 豆包MarsCode AI刷题

66 阅读3分钟

比赛配对问题

问题理解

题目描述了一个比赛赛制,其中队伍数 n 会根据奇偶性进行不同的配对和晋级规则,直到决出唯一的获胜队伍。我们需要计算在整个比赛过程中进行的配对次数。

数据结构与算法选择

由于我们只需要计算配对次数,而不需要实际模拟每一场比赛的具体配对情况,因此我们可以使用一个简单的循环来处理这个问题。

算法步骤

  1. 初始化:定义一个变量 matches 来记录总的配对次数,初始值为0。
  2. 循环处理
    • 当队伍数 n 大于1时,继续循环。
    • 如果 n 是偶数,配对次数增加 n / 2,剩余队伍数变为 n / 2
    • 如果 n 是奇数,配对次数增加 (n - 1) / 2,剩余队伍数变为 (n - 1) / 2 + 1
  3. 返回结果:当 n 变为1时,循环结束,返回 matches

代码框架

def solution(n: int) -> int:
    matches = 0  # 初始化配对次数
    while n > 1:  # 当队伍数大于1时继续循环
        if n % 2 == 0:  # 如果队伍数是偶数
            matches += n // 2  # 配对次数增加 n / 2
            n //= 2  # 剩余队伍数为 n / 2
        else:  # 如果队伍数是奇数
            matches += (n - 1) // 2  # 配对次数增加 (n - 1) / 2
            n = (n - 1) // 2 + 1  # 剩余队伍数为 (n - 1) / 2 + 1
    return matches  # 返回总配对次数

打点计数器的区间合并

问题理解

我们需要设计一个打点计数器,它可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。最终,我们需要计算在给定的多组数字范围内,计数器会打多少个点。

数据结构选择

  • 区间列表:我们使用一个列表来存储输入的区间。
  • 合并后的区间列表:我们使用另一个列表来存储合并后的区间。

算法步骤

  1. 排序区间:首先,我们需要对输入的区间进行排序。排序可以基于区间的起始值。
  2. 合并区间:遍历排序后的区间列表,合并重叠的区间。
  3. 计算唯一数字的数量:合并后的区间将不再有重叠,我们可以直接计算每个区间内的数字数量,并累加得到最终结果。

详细步骤

  1. 排序区间

    • 使用 inputArray.sort(key=lambda x: x[0]) 对区间按起始值排序。
  2. 合并区间

    • 初始化一个空列表 merged_intervals 来存储合并后的区间。
    • 使用两个变量 current_startcurrent_end 来跟踪当前合并的区间。
    • 遍历排序后的区间列表:
      • 如果当前区间的起始值小于或等于 current_end,说明有重叠,更新 current_end 为当前区间和前一个区间的最大结束值。
      • 如果没有重叠,将当前合并的区间添加到 merged_intervals 中,并更新 current_startcurrent_end 为当前区间的起始值和结束值。
    • 遍历结束后,将最后一个合并的区间添加到 merged_intervals 中。
  3. 计算唯一数字的数量

    • 初始化一个计数器 count
    • 遍历合并后的区间列表,对于每个区间 [start, end],计算区间内的数字数量 end - start + 1,并累加到 count 中。

代码实现

def solution(inputArray):
    # 1. 对区间进行排序
    inputArray.sort(key=lambda x: x[0])
    
    # 2. 合并区间
    merged_intervals = []
    current_start, current_end = inputArray[0]
    
    for start, end in inputArray[1:]:
        if start <= current_end:  # 有重叠
            current_end = max(current_end, end)
        else:  # 没有重叠
            merged_intervals.append([current_start, current_end])
            current_start, current_end = start, end
    
    # 添加最后一个区间
    merged_intervals.append([current_start, current_end])
    
    # 3. 计算唯一数字的数量
    count = 0
    for start, end in merged_intervals:
        count += end - start + 1
    
    return count

if __name__ == "__main__":
    testArray1 = [[1, 4], [7, 10], [3, 5]]
    testArray2 = [[1, 2], [6, 10], [11, 15]]

    print(solution(testArray1) == 9)
    print(solution(testArray2) == 12)