最大和最小差(贪心算法)

Posted

技术标签:

【中文标题】最大和最小差(贪心算法)【英文标题】:Maximum and Minimum difference (greedy algorithm) 【发布时间】:2021-11-19 13:21:35 【问题描述】:

问题: 给你一个数组 A,有 n 个元素。你必须从数组中删除 n/2 个元素并将其添加到另一个数组 B (最初为空)。找到差异的最大值和最小值 这两个数组之间。这两个数组之间的区别是 总和(绝对值(A[i]-B[i])。

该代码仅在数组 (N) 的大小为偶数时才有效。 有人可以提供一个解决方案,当数组的大小也是奇数时也可以工作。

#include <bits/stdc++.h>

using namespace std;     
//This code only works for even number of elements        

int main()      
    int n;  
    cin>>n;   
    vector<int> a(n);    
    for(int i=0;i<n;i++)      
        cin>>a[i];        
           
    sort(a.begin(), a.end());       
    long long mn = 0,mx = 0;               
    for(int i=0;i<n/2;i++)    
        mx+=a[i+n/2]-a[i];         
        mn+=a[2*i+1]-a[2*i];        
    

    cout<<abs(mn)<<" "<<abs(mx)<<" ";
    return 0;

【问题讨论】:

问题陈述清楚地暗示n 是偶数,对于奇数n 没有意义。当n 为奇数时,没有办法“完全删除n/2 元素”,因为显然无法删除半个元素。 【参考方案1】:

对我来说,我喜欢将工作拆分,以便轻松可视化在算法中可以提高效率的地方。以下与您的解决方案非常相似,但适用于偶数和奇数长度向量。排序的平均运行时间为 O(nlogn),向量的空间复杂度为 O(n)。

// Given two arrays of equal length, returns their "Difference", O(n) runtime
int ArrayDiff(vector<int> A, vector<int> B)

    if (A.size() != B.size() || A.size() == 0) return -1;

    int sum = 0;
    for (int i = 0; i < A.size(); i++)
    
        sum += abs(A[i] - B[i]);
    
    return sum;


// Given a vector arr, find the max and min "Difference"
void PrintMaxAndMin(vector<int> arr)

    int n = arr.size();
    if (n <= 0) return;
    vector<int> Amax, Amin, Bmax, Bmin ;

    // for each iteration of removing n/2 elements, we find the max and min of the arrays
    sort(arr.begin(), arr.end());

    for (int i = 0; i < n/2; i++)
    
        Amax.push_back(arr[i]);
        Bmax.push_back(arr[n-i-1]);

        Amin.push_back(arr[n-i-1]);
        Bmin.push_back(arr[n-i-2]);
    

    cout << ArrayDiff(Amax, Bmax) << " " << ArrayDiff(Amin, Bmin) << endl;


// Run the above functions on a vector of odd and even sizes
int main()      
    vector<int> arr_even =  4,3,2,1 ;
    cout << "Even Length Vector: ";
    PrintMaxAndMin(arr_even);

    vector<int> arr_odd =  5,4,3,2,1 ;
    cout << "Odd Length Vector: ";
    PrintMaxAndMin(arr_odd);

    return 0;

下面是工作示例:live example。希望这会有所帮助。

程序输出:

Program stdout
Even Length Vector: 4 2
Odd Length Vector: 6 2

【讨论】:

您给出的代码对于奇数和偶数大小返回相同的输出。测试用例:vector arr_even = 4,3,2,1 ;矢量 arr_odd = 5,4,3,2,1;输出:偶数长度向量:4 2 奇数长度向量:4 2 哎呀更新了奇数长度的向量。 感谢您的代码,但我还有一个疑问。问题是数组需要精确地分成两半,那么如何计算奇数个元素? 如果输入向量是奇数并且向量已排序,我使用索引将向量分成两半,具体取决于会产生更大的最大值和更小的最小值。 IE。如果 arr = 1, 2, 3 并且我想找到 ABmin。那么 Amin=1,Bmin=3 比 Amin=2,Bmin=3 差。不知道这是否让你更困惑。 是的,我真的很困惑,你能解释清楚吗?

以上是关于最大和最小差(贪心算法)的主要内容,如果未能解决你的问题,请参考以下文章

贪心算法之prim算法的证明

贪心算法的复习和总结

28-算法训练 最大最小公倍数 -贪心

贪心算法:K次取反后最大化的数组和

蓝书1.1 贪心

五分钟了解一下什么是「贪心算法 」