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

Swap the elements of two sequences, such that the difference of the element-sums gets minimal.

本文关键字:元素 和的 两个 交换      更新时间:2023-10-16

一个面试问题:

给定两个非有序整数序列ab,它们的大小为n数是随机选择的:将ab的元素交换,使得a的元素之和减去b的元素之总和最小。

举个例子:

a = [ 5 1 3 ]
b = [ 2 4 9 ]

结果是(1+2+3)-(4+5+9)=-12。

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

有什么想法吗?

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

python或C++思维是首选。

修订的解决方案:

  1. 合并两个列表x=合并(a,b)。

  2. 计算x的中值(复杂度O(n)参见http://en.wikipedia.org/wiki/Selection_algorithm)

  3. 使用a和b之间的中值交换元素。也就是说,在a中找到一个小于中值的元素,在b中找到一一个大于中值的元素并交换它们

最终复杂度:O(n)

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

我脑海中浮现的是以下算法大纲:

  1. C=A对B
  2. 部分排序#A(A的个数)C的元素
  3. 从C中减去前#A个元素的和,减去C中最后#B个元素的总和

您应该注意到,不需要对所有元素进行排序,只要找到A最小元素的数量就足够了。举个例子:

  1. C={5,1,3,2,4,9}
  2. C={1,2,3,5,4,9}
  3. (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;
}