伴学笔记 AI刷题 404 小Q的奇偶数操作数组 | 豆包MarsCode AI刷题

52 阅读4分钟

这道题目需要对一个数组 a 执行 k 次操作,目的是通过合适的选择和操作,使得操作后的数组元素和最小。

  • 如果选中的数字 x 是 奇数,则 x = x * 2,即将 x 乘以 2。
  • 如果选中的数字 x 是 偶数,则 x = x * 2 + 1,即将 x 乘以 2 后再加 1。

这些操作会使得数组的元素值增大,但我们需要通过合理选择进行 k 次操作,以确保最终的数组和最小。

我们可以通过以下几点来分析如何做出合理的决策:

  1. 奇数操作的特性:
    当对一个奇数执行操作时,x = x * 2 会导致 x 变成偶数。这意味着我们对奇数的操作会让它变得更大,因此应尽量对奇数操作。具体来说,奇数变成偶数后,下一次再对它进行操作时,它会变得更大。
  2. 偶数操作的特性:
    对偶数执行操作时,x = x * 2 + 1 会让 x 变成一个更大的奇数。因此,偶数在操作后会快速变大。
  3. 选择策略:
    由于偶数操作后加 1,实际上偶数的增幅比奇数的增幅要大。因此,应该优先对最小的偶数进行操作。由于我们希望最终的数组和尽可能小,因此最优策略是:每次操作都选择当前最小的元素进行操作,因为操作会使选中的元素变大。

所以构建解法如下:

def solution(n: int, k: int, a: list)
    times = k
    while times > 0:
        # 找到当前数组中最小的元素
        min_index = a.index(min(a))
        if a[min_index] % 2 == 1:
            a[min_index] *= 2
        else:
            a[min_index] = a[min_index] * 2 + 1
        times -= 1
    
    # 计算操作后的数组和
    return sum(a)

这个解法使用了贪心算法,每次选择当前数组中的最小值进行操作,从而确保每次操作对总和的影响最小。该算法的时间复杂度是 O(k * n),适合用于数组较小或 k 较小的情况。贪心算法是一种在解决问题时,做出一系列选择的策略,每一步都选择当前看起来最好的选项,而不考虑后续可能的影响。简单来说,贪心算法的核心思想是每一步选择当前局部最优解,最终希望得到一个全局最优解。

贪心算法通常适用于以下情况:

  1. 问题的每个选择都能按照某种方式度量“好坏”。
  2. 局部最优解能导致全局最优解(即贪心选择性质)。

贪心算法通常具有较低的时间复杂度,但它并不一定能保证得到全局最优解,除非问题本身具备特定的性质(如最优子结构)。

贪心算法的步骤

  1. 定义选择策略:明确每次做选择时应选择哪个选项。
  2. 贪心选择:每一步都做出当前最优的选择。
  3. 可行性检查:确保做出的选择是有效的,不会违反约束条件。
  4. 优化:在所有选择完成后,通过结果来优化目标函数(例如最小化成本、最大化效益等)。

经典例子:活动选择问题

假设有多个活动,它们的开始时间和结束时间已知,目标是选择最多数量的互不冲突的活动。我们可以通过贪心算法来选择活动,选择每次结束时间最早的活动,以确保后续有更多的时间选择其他活动。

# 定义一个活动选择函数
def activity_selection(start, finish):
    # 活动数量
    n = len(start)
    
    # 按照结束时间对活动进行排序
    activities = list(zip(start, finish))
    activities.sort(key=lambda x: x[1])
    
    # 选择第一个活动
    selected_activities = [activities[0]]
    last_finish_time = activities[0][1]
    
    # 从第二个活动开始,选择与上一个活动不冲突的活动
    for i in range(1, n):
        if activities[i][0] >= last_finish_time:
            selected_activities.append(activities[i])
            last_finish_time = activities[i][1]
    
    # 返回选择的活动列表
    return selected_activities

# 示例数据
start_times = [1, 3, 0, 5, 8, 5]
finish_times = [2, 4, 6, 7, 9, 9]

# 执行活动选择
result = activity_selection(start_times, finish_times)

# 输出选择的活动
for activity in result:
    print(f"Start: {activity[0]}, Finish: {activity[1]}")

这个问题展示了贪心算法的核心思想:每次选择当前能带来最优结果的选项(即最早结束的活动)。贪心算法简单且效率高,但并不是所有问题都能保证全局最优解,因此在使用时需要注意问题的性质。