AI刷题第275题:最小化数组极值(分类讨论)| 豆包MarsCode AI刷题

45 阅读3分钟

问题描述

小F手里有一个长度为nn的数组,他可以选择删除数组中的任意两个元素,并将它们的和作为一个新元素放回数组中。他最多可以进行一次这样的操作。小F的目标是使得数组的极值(即数组最大值减去最小值)尽可能小。现在你需要帮助小F计算出在最优操作下,数组能达到的最小极值。


测试样例

样例1:

输入:n = 7 ,a = [1, 4, 3, 3, 2, 2, 3]
输出:2

样例2:

输入:n = 5 ,a = [10, 5, 6, 7, 3]
输出:4

样例3:

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

问题描述优化

小F手中有一个长度为 n 的数组,他可以选择删除数组中的任意两个元素,并将它们的和作为一个新元素放回数组中。目标是使得数组的极值(即数组最大值减去最小值)尽可能小。我们需要分析在最优操作下,数组能达到的最小极值。

情况一:数组中不存在负数

在这种情况下,我们不能通过删除和合并操作来减小最大值。因此,我们只能通过选择最小的两个值相加,尽可能提高最小值。具体步骤如下:

  1. 寻找最小值:找到数组中最小的两个值 a 和 b。
  2. 计算新元素:将这两个最小值相加得到新元素 c = a + b。
  3. 新数组极值计算
    • 新数组的最小值为 max(c, 第三小的值)。
    • 新数组的最大值为 max(原最大值, c)。
  4. 比较极值差:计算新数组的极值差(新最大值 - 新最小值),并与未进行操作前的极值差进行比较,取较小值作为最终结果。

情况二:数组中存在负数

当数组中有负数时,我们可以通过合并负数和正数来有效减小极值。具体处理方式如下:

  1. 寻找关键值:遍历数组,找到最大的两个值(max1, max2)和最小的三个值(min1, min2, min3)。
  2. 新元素计算
    • 选择 min1 和 max1 进行相加,得到新元素 c = min1 + max1。
  3. 新数组极值计算
    • 新数组的最小值为 min(min2, c)。
    • 新数组的最大值为 max(max2, c)。
  4. 比较极值差:计算新数组的极值差,并与未进行操作前的极值差进行比较,取较小值作为最终结果。

特殊情况处理

题目中强调最多进行一次操作,也就是说可以选择不进行任何操作。在这种情况下,我们需要预先记录未进行操作前的极值差,以便在后续比较中得到最终的最小极值差。

总结

通过上述分析,我们能够有效地计算出在一次操作后,数组可能达到的最小极值。无论是针对非负数的情况,还是存在负数的情况,我们都能找到合适的策略来优化极值差。

代码呈现

#include <iostream>
#include <vector>
#include <string>
#include <climits>

using namespace std;

int solution(int n, vector<int> a) {
    // write code here
    if(n==1) return 0;
    int maxNum = INT_MIN,secMaxNum=INT_MAX;
    int minNum = INT_MAX;
    int secMinNum = INT_MAX,thirdMinNum=INT_MAX;
    for(int i=0;i<a.size();++i){
        if(a[i]>=maxNum) {
            secMaxNum = maxNum;
            maxNum = a[i];
        }
        else if(a[i]>secMaxNum){
            secMaxNum = a[i];
        }

        if(a[i]<=minNum){
            thirdMinNum = secMinNum;
            secMinNum = minNum;
            minNum = a[i];
        }
        else if(a[i]<=secMinNum){
            thirdMinNum = secMinNum;
            secMinNum = a[i];
        }
        else if(a[i]<thirdMinNum){
            thirdMinNum = a[i];
        }
    }

    int newNum = 0;
    int initDiff = maxNum-minNum;
    if(minNum<0){
        newNum = minNum+maxNum;
        maxNum = max(secMaxNum,newNum);
        minNum = min(secMinNum,newNum);
    }
    else{
        newNum = minNum+secMinNum;
        maxNum = max(maxNum,newNum);
        minNum= min(thirdMinNum,newNum);
    }

    return min(maxNum-minNum,initDiff);
}

int main() {
    cout << (solution(7, {1, 4, 3, 3, 2, 2, 3}) == 2) << endl;
    cout << (solution(5, {10, 5, 6, 7, 3}) == 4) << endl;
    cout << (solution(4, {1, 1, 1, 1}) == 0) << endl;
    return 0;
}