AI 刷题 404.小Q的奇偶操作数组 题解 | 豆包MarsCode AI刷题

104 阅读4分钟

404.小Q的奇偶操作数组

  • 问题描述

小Q有一个长度为 n 的数组,他可以进行 k 次操作,每次操作可以对数组中的任意一个数字执行以下操作:

  1. 如果选择的数字 x 是奇数,则将 x 乘以 2,即 x =x × 2。
  2. 如果选择的数字 x 是偶数,则将x 乘以 2 再加 1,即 x = x × 2 + 1。

小Q想知道,经过 k 次操作后,数组的元素之和最小可以是多少。

  • 思路解析

我们需要在数组 a 中进行 k 次操作,每次操作可以选择一个数字进行特定的变换(奇数乘以2,偶数乘以2再加1),目标是使得经过 k 次操作后,数组的元素之和最小。

  • 解题思路

  1. 初始和计算:首先计算数组的初始和。
  2. 优先操作:为了使数组的和最小,我们应该优先选择那些操作后增加值最小的数字进行操作。
  3. 操作选择:对于每个数字,计算其操作后的值,并选择增加值最小的操作。
  4. 重复操作:重复上述步骤 k 次。
  • 详细步骤

  1. 初始和计算

    • 计算数组的初始和,即 current_sum = sum(a)
  2. 优先操作

    • 每次操作时,遍历数组中的每个元素,计算对其进行操作后的增加值。
    • 对于奇数 x,操作后的值为 x * 2,增加值为 (x * 2) - x
    • 对于偶数 x,操作后的值为 x * 2 + 1,增加值为 (x * 2 + 1) - x
  3. 操作选择

    • 在每次操作中,选择增加值最小的数字进行操作。
    • 记录最小增加值和对应的索引。
  4. 重复操作

    • 重复上述步骤 k 次,每次操作后更新数组的和。
  • 数据结构选择

    • 使用数组 a 存储原始数据。
    • 使用变量 current_sum 存储当前数组的和。
    • 使用变量 min_increase 和 min_index 记录每次操作的最小增加值和对应的索引。
  • 算法步骤

  1. 计算数组的初始和 current_sum

  2. 进行 k 次操作:

    • 初始化 min_increase 为无穷大,min_index 为 -1。
    • 遍历数组 a,计算每个元素操作后的增加值。
    • 选择增加值最小的元素进行操作,并更新 min_increase 和 min_index
    • 对选中的元素进行操作,更新数组的和 current_sum
  3. 返回最终的数组和 current_sum

  • 难点总结

  1. 操作选择策略

    • 问题:在每次操作中,如何选择最优的数字进行操作,以使得数组的和最小。
    • 难点:需要计算每个数字操作后的增加值,并选择增加值最小的数字进行操作。这涉及到对数组中每个元素的遍历和比较。
  2. 重复操作的复杂性

    • 问题:需要进行 k 次操作,每次操作都需要重新计算和选择最优的数字。
    • 难点:随着操作次数的增加,计算量也会增加,如何高效地进行多次操作是一个挑战。
  3. 增加值的计算

    • 问题:对于每个数字,需要计算其操作后的增加值。
    • 难点:奇数和偶数的操作方式不同,需要分别计算增加值,并选择最小的增加值进行操作。
  4. 数组和的更新

    • 问题:每次操作后,需要更新数组的和。
    • 难点:确保每次操作后正确更新数组的和,避免计算错误。
  • 代码部分

def solution(n: int, k: int, a: list) -> int:
    # 计算初始和
    current_sum = sum(a)
    
    # 进行 k 次操作
    for _ in range(k):
        # 初始化最小增加值和对应的索引
        min_increase = float('inf')
        min_index = -1
        
        # 遍历数组,找到增加值最小的操作
        for i in range(n):
            if a[i] % 2 == 1:  # 奇数
                increase = (a[i] * 2) - a[i]
            else:  # 偶数
                increase = (a[i] * 2 + 1) - a[i]
            
            # 更新最小增加值和对应的索引
            if increase < min_increase:
                min_increase = increase
                min_index = i
        
        # 对选中的数字进行操作
        if a[min_index] % 2 == 1:  # 奇数
            a[min_index] *= 2
        else:  # 偶数
            a[min_index] = a[min_index] * 2 + 1
        
        # 更新当前和
        current_sum += min_increase
    
    return current_sum

if __name__ == '__main__':
    print(solution(5, 3, [1, 2, 3, 5, 2]) == 20)
    print(solution(3, 2, [7, 8, 9]) == 40)
    print(solution(4, 4, [2, 3, 5, 7]) == 33)