青训营伴学笔记丨MarsCode刷题日记丨数组极差最小化问题

58 阅读2分钟

题目背景

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

测试样例

样例1:

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

样例2:

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

样例3:

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

思路

  1. 遍历所有可能的合并操作

    • 对于数组中的每一对相邻元素,计算合并后的新数组。
    • 计算新数组的极差。
  2. 选择极差最小的合并操作

    • 记录所有合并操作后的极差,选择最小的那个。

数据结构选择

  • 使用数组来存储原始数组和合并后的数组。
  • 使用变量来记录最小极差。

算法步骤

  1. 初始化一个变量 min_range 为一个大数(例如 INT_MAX)。

  2. 遍历数组中的每一对相邻元素:

    • 计算合并后的新数组。
    • 计算新数组的极差。
    • 更新 min_range 为当前极差和 min_range 中的较小值。
  3. 返回 min_range

通过这种方式,可以找到执行一次合并操作后,数组的极差的最小可能值。

题解代码

int solution(int n, vector<int> a) {
    // 初始化最小极差为一个很大的数
    int min_range = 1000000;
    
    // 遍历数组中的每一对相邻元素
    for (int i = 0; i < n - 1; ++i) {
        // 计算合并后的新数组
        vector<int> new_array = a;
        new_array[i] = new_array[i] + new_array[i + 1];
        new_array.erase(new_array.begin() + i + 1); // 删除合并后的元素
        
        // 计算新数组的极差
        int max_val = *max_element(new_array.begin(), new_array.end());
        int min_val = *min_element(new_array.begin(), new_array.end());
        int current_range = max_val - min_val;
        
        // 更新最小极差
        min_range = min(min_range, current_range);
    }
    
    return min_range;
}

步骤解释

  1. 初始化最小极差:使用 INT_MAX 初始化 min_range,确保任何极差都会比它小。
  2. 遍历相邻元素:使用 for 循环遍历数组中的每一对相邻元素。
  3. 合并操作:将相邻的两个元素合并,并更新数组。
  4. 计算极差:使用 max_element 和 min_element 函数计算新数组的最大值和最小值,然后计算极差。
  5. 更新最小极差:使用 min 函数更新 min_range

优化思路

  1. 避免创建新数组:可以直接在原数组上进行操作,而不需要创建新的数组。
  2. 减少不必要的操作:在计算极差时,可以直接使用原数组的最大值和最小值,而不需要每次都重新计算。