C++ 交换两个序列的元素,使元素和的差最小。

C++ 交换两个序列的元素,使元素和的差最小。,c++,python,algorithm,data-structures,C++,Python,Algorithm,Data Structures,采访问题: 给定两个非有序整数序列a和b,它们的大小都是n 随机选择数字:交换a和b的元素,这样a的元素之和减去b的元素之和是最小的 举个例子: a = [ 5 1 3 ] b = [ 2 4 9 ] 结果是(1+2+3)-(4+5+9)=-12 我的算法是:将它们排序在一起,然后将第一个最小的n整数放在a中,剩下的放在b中。它在时间上是O(n lgn),在空间上是O(n)。我不知道如何将其改进为时间上为O(n),空间上为O(1)的算法。O(1)意味着我们不需要更多的额外空间,除了序号1和序号

采访问题:

给定两个非有序整数序列
a
b
,它们的大小都是n 随机选择数字:交换
a
b
的元素,这样
a
的元素之和减去
b
的元素之和是最小的

举个例子:

a = [ 5 1 3 ]
b = [ 2 4 9 ]
结果是(1+2+3)-(4+5+9)=-12

我的算法是:将它们排序在一起,然后将第一个最小的
n
整数放在
a
中,剩下的放在
b
中。它在时间上是O(n lgn),在空间上是O(n)。我不知道如何将其改进为时间上为O(n),空间上为O(1)的算法。O(1)意味着我们不需要更多的额外空间,除了序号1和序号2本身

有什么想法吗

另一个问题是:如果我们需要最小化差异的绝对值(最小化
| sum(a)-sum(b)|
),该怎么办

Python或C++思维优先。

< P>修订后的解决方案:

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    // Initialize 'a' and 'b'
    int ai[] = { 5, 1, 3 };
    int bi[] = { 2, 4, 9 };
    std::vector<int> a(ai, ai + 3);
    std::vector<int> b(bi, bi + 3);

    // 'c' = 'a' merged with 'b'
    std::vector<int> c;
    c.insert(c.end(), a.begin(), a.end());
    c.insert(c.end(), b.begin(), b.end());

    // partitially sort #a elements of 'c'
    std::partial_sort(c.begin(), c.begin() + a.size(), c.end());

    // build the difference
    int result = 0;
    for (auto cit = c.begin(); cit != c.end(); ++cit)
        result += (cit < c.begin() + a.size()) ? (*cit) : -(*cit);

    // print result (and it's -12)
    std::cout << result << std::endl;
}
  • 合并两个列表x=合并(a,b)

  • 计算x的中位数(复杂度O(n)见)

  • 使用此中间值在a和b之间交换元素。也就是说,在a中找到一个小于中位数的元素,在b中找到一个大于中位数的元素,然后交换它们

  • 最终复杂度:O(n)


    最小化绝对差是NP完全的,因为它相当于背包问题。

    我想到的是以下算法大纲:

  • C=A v B
  • 对C的A(A个数)元素进行部分排序
  • 用C中第一个A元素的和减去C中最后一个B元素的和
  • 您应该注意到,不需要对所有元素进行排序,只需找到最小元素的数量即可。你的例子如下:

  • C={5,1,3,2,4,9}
  • C={1,2,3,5,4,9}
  • (1+2+3)-(5+4+9)=-12
  • 一个C++解决方案:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main()
    {
        // Initialize 'a' and 'b'
        int ai[] = { 5, 1, 3 };
        int bi[] = { 2, 4, 9 };
        std::vector<int> a(ai, ai + 3);
        std::vector<int> b(bi, bi + 3);
    
        // 'c' = 'a' merged with 'b'
        std::vector<int> c;
        c.insert(c.end(), a.begin(), a.end());
        c.insert(c.end(), b.begin(), b.end());
    
        // partitially sort #a elements of 'c'
        std::partial_sort(c.begin(), c.begin() + a.size(), c.end());
    
        // build the difference
        int result = 0;
        for (auto cit = c.begin(); cit != c.end(); ++cit)
            result += (cit < c.begin() + a.size()) ? (*cit) : -(*cit);
    
        // print result (and it's -12)
        std::cout << result << std::endl;
    }
    
    #包括
    #包括
    #包括
    int main()
    {
    //初始化“a”和“b”
    int ai[]={5,1,3};
    int-bi[]={2,4,9};
    std::载体a(ai,ai+3);
    std::向量b(bi,bi+3);
    //“c”=“a”与“b”合并
    std::向量c;
    c、 插入(c.end(),a.begin(),a.end());
    c、 插入(c.结束(),b.开始(),b.结束());
    //部分排序#c的a元素
    部分排序(c.begin(),c.begin()+a.size(),c.end());
    //创造差异
    int结果=0;
    对于(自动cit=c.begin();cit!=c.end();++cit)
    结果+=(citSTD:CUT听起来像一个家庭作业。如果是这样,请标记。如果你不考虑原始A和B列表,那么它不能在空间中O(1)。如果你不考虑它们,那么只需直接交换值。在任何一种情况下,请提供更多的问题细节。@ GaretJax,如何与O(n)有效地交换。时间?只需为单个元素(O(1)空间)使用一个临时变量,并在列表(O(n)时间)上迭代即可。-1“交换a和b的元素”非常模糊——我在回答中发现了大约2.01种理解。你能解释一下等价性吗?我似乎很清楚,OP的排序解决方案和将最小值放入a中将最小化总和(a)-总和(b):我缺少什么?你是在说第二部分(最小化绝对值)或者两者都有?因为我认为它不适用于第一个,为了获得最大的负差,将n/2最小的数字放在一个列表中,而将n/2最大的数字放在另一个列表中,正如OP所说的那样。@DSM我以为你在计算绝对最小值。如果是最小值,则使用新的解决方案。不需要排序:)对于中位数,你必须对x!I如果你对x排序,复杂性不是O(n)。@ChristianAmmer可以在O(n)中找到中值。请看:这不是O(n),而是O(n logN/2),如果我们想要最佳解(即n/2最小值)。@Voo:你是对的,但是O(n)算法存在吗?我想不出任何算法?我认为中值解也不是O(n),为了得到中位数,必须对序列进行排序,否则你会从中间选择一个随机元素(或者我错了吗)?哦,我同意O(N logn/2)似乎是最好的解决方案。毕竟我们需要N/2最小值,我真的不知道在O(N)中这是怎么可能的。