交换两个序列的元素,使元素和的差异变得最小。

时间:2012-01-28 19:29:00

标签: c++ python algorithm data-structures

面试问题:

  

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

举个例子:

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

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

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

有什么想法吗?

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

首选python或C ++思想。

2 个答案:

答案 0 :(得分:8)

修订解决方案:

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

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

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

  4. 最终复杂性:O(n)

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

答案 1 :(得分:2)

我想到的是遵循算法大纲:

  1. C = A v B
  2. 对C
  3. 的#A(A个数)元素进行部分排序
  4. 从C中的第一个#A元素的总和中减去C中最后一个#B元素的总和。
  5. 您应该注意到,不需要对所有元素进行排序,只需找到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
    4. 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;
      }