【264】数组极差最小化问题 | 豆包MarsCode AI刷题

327 阅读5分钟

问题描述

小M有一个数组,她可以执行一次操作:选择两个相邻的元素并将它们合并,合并后的新元素值为原来两个元素的和。合并操作之后,数组的长度将减少1。小M想知道,执行一次操作后,数组的极差(最大值减去最小值)的最小可能值是多少。

示例

样例1

Copy Code
输入:n = 3, a = [1, 4, 5]
输出:0

样例2

Copy Code
输入:n = 5, a = [3, 6, 2, 8, 7]
输出:5

样例3

Copy Code
输入:n = 4, a = [10, 20, 30, 40]
输出:10

解题思路

我们可以通过模拟所有可能的合并操作来求解这个问题。每次合并两个相邻的元素后,数组的长度减少1,且这个新的元素将代替原有的两个元素。最终我们希望能够找出在执行一次合并操作后,数组的极差(即最大值减去最小值)可能的最小值。

主要思路:

  1. 极差定义

    • 数组的极差就是最大值与最小值的差,表示数组中数值的波动幅度。
  2. 操作限制

    • 只有一次合并操作,且操作只能选择两个相邻的元素。
    • 每次合并操作后的新数组长度会减小1。
  3. 目标

    • 在合并后,计算数组的极差,并找到可能的最小极差。

解题步骤

  1. 边界条件

    • 如果数组的长度为1,说明没有可合并的元素,极差已经为0。
  2. 遍历所有相邻元素对进行合并

    • 选择数组中每对相邻的元素,将它们合并,得到一个新的数组。
    • 计算这个新数组的极差,即计算最大值与最小值的差。
  3. 计算每次合并后的极差

    • 对每个可能的合并操作,生成新的数组,并计算新的极差。
  4. 更新最小极差

    • 使用变量来记录当前所有可能极差中的最小值,最终返回这个最小值。

解题代码

pythonCopy Code
def solution(n: int, a: list) -> int:
    # 如果数组只有一个元素,极差为0
    if n == 1:
        return 0
    
    # 初始化最小极差为正无穷大
    min_range = float('inf')
    
    # 遍历数组,考虑所有可能的合并操作
    for i in range(n - 1):
        # 对于每一个相邻的元素进行合并,产生新的数组
        new_a = a[:i] + [a[i] + a[i + 1]] + a[i + 2:]
        
        # 计算合并后的数组的极差(最大值 - 最小值)
        range_after_merge = max(new_a) - min(new_a)
        
        # 更新最小极差
        min_range = min(min_range, range_after_merge)
    
    # 返回计算得到的最小极差
    return min_range

if __name__ == '__main__':
    # 测试样例
    print(solution(3, [1, 4, 5]))  # 输出: 0
    print(solution(5, [3, 6, 2, 8, 7]))  # 输出: 5
    print(solution(4, [10, 20, 30, 40]))  # 输出: 10

解题思路详细解析

极差的定义

极差是指一个数组中最大值与最小值之间的差异。对于给定数组 a = [a1, a2, a3, ..., an],其极差就是 max(a) - min(a)。在本问题中,我们的目标是通过合并操作后,使得数组的极差最小。

合并操作的限制

  • 合并操作只能选择相邻的两个元素,合并后的元素值为它们的和。
  • 合并后的新数组长度将减少1,因此我们最终希望通过合并操作,尽可能让数组的极差变小。

最小化极差的策略

通过遍历数组中的每一对相邻元素进行合并,我们可以模拟出多个合并结果,每个合并操作都会影响数组的最大值和最小值。最终,我们需要计算并返回所有合并结果中的最小极差。

详细步骤

  1. 初始化

    • 如果数组长度为1,直接返回0。
    • 初始化最小极差为正无穷大,以便后续更新最小极差。
  2. 遍历数组

    • 对于每一对相邻的元素进行合并。
    • 对于每个合并操作,生成新的数组 new_a,计算其极差并更新最小极差。
  3. 返回结果

    • 返回所有合并后的数组极差中的最小值。

示例解析

示例1

输入:n = 3, a = [1, 4, 5]

  • 初始数组的极差为 5 - 1 = 4

  • 合并可能性:

    • 合并 1 和 4,得到新数组 [5, 5],极差为 5 - 5 = 0
    • 合并 4 和 5,得到新数组 [1, 9],极差为 9 - 1 = 8
  • 最小极差为 0

示例2

输入:n = 5, a = [3, 6, 2, 8, 7]

  • 初始数组的极差为 8 - 2 = 6

  • 合并可能性:

    • 合并 3 和 6,得到新数组 [9, 2, 8, 7],极差为 9 - 2 = 7
    • 合并 6 和 2,得到新数组 [3, 8, 8, 7],极差为 8 - 3 = 5
    • 合并 2 和 8,得到新数组 [3, 6, 15, 7],极差为 15 - 3 = 12
    • 合并 8 和 7,得到新数组 [3, 6, 2, 15],极差为 15 - 2 = 13
  • 最小极差为 5

示例3

输入:n = 4, a = [10, 20, 30, 40]

  • 初始数组的极差为 40 - 10 = 30

  • 合并可能性:

    • 合并 10 和 20,得到新数组 [30, 30, 40],极差为 40 - 30 = 10
    • 合并 20 和 30,得到新数组 [10, 50, 40],极差为 50 - 10 = 40
    • 合并 30 和 40,得到新数组 [10, 20, 70],极差为 70 - 10 = 60
  • 最小极差为 10

复杂度分析

时间复杂度

  • 遍历所有相邻元素对的次数是 n - 1
  • 对于每次合并操作,生成的新数组的极差需要计算最大值和最小值,这需要遍历整个数组,时间复杂度为 O(n)
  • 因此,总的时间复杂度是 O(n^2)

空间复杂度

  • 每次合并操作生成一个新的数组,大小为 n - 1,因此空间复杂度为 O(n)

总结

本问题通过模拟所有可能的合并操作,计算每次合并后的数组极差,从而找出最小的极差。使用暴力遍历的方法,可以在保证正确性的同时,得出最优解。