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;
}
最小化绝对差是NP完全的,因为它相当于背包问题。我想到的是以下算法大纲:
一个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)
结果+=(cit STD: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)中这是怎么可能的。