面试问题:
给定两个非有序整数序列
a
和b
,它们的大小为n,all 数字是随机选择的:交换a
和b
的元素,使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 ++思想。
答案 0 :(得分:8)
修订解决方案:
合并两个列表x = merge(a,b)。
计算x的中位数(复杂度O(n)见http://en.wikipedia.org/wiki/Selection_algorithm)
在a和b之间使用此中位数交换元素。也就是说,找到一个小于中位数的元素,在b中找到一个大于中位数的元素并交换它们
最终复杂性:O(n)
最小化绝对差值是NP完全,因为它等同于背包问题。
答案 1 :(得分:2)
我想到的是遵循算法大纲:
您应该注意到,不需要对所有元素进行排序,只需找到A个最小元素的数量即可。给出的例子:
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;
}