闲来无事,看到了一篇文章,华为面试题,题目如下:
有两个数组a,b,大小都为n,数组元素的值任意,无序;
要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
网址是http://bbs.chinaunix.net/thread-855126-1-1.html这个。
估计多数人想到的都是先sort,再交叉,或者一条龙什么的,包括我。后来一想不对啊,如果前面的都是个位数,最后一个是999怎么办?
抱着学习的态度一页一页往下翻,好多人都是在提出来自己想法,但是我拿我这个999验证一下,都不对!(⊙﹏⊙)b 汗!!后来我自己也想了好久,八分钟肯定是有了,不过接着就想到了背包算法。
先把最重的放进a,次重的放b,此时一定是sum(a) >sum(b),再把第三个放进b里,如果这时候sum(a) < sum(b),第四个放a里面,否则放b里。以此类推,谁轻就先放谁,值到有一个先充满了10,再把剩下的放入到另一个中去。算法应该不算是最优的,我清楚的很,不过起码靠谱多了。代码如下,我写的代码那就更没法看了
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
#include <algorithm>
#include <istream>
#include <ostream>
#include <iostream>
#include <string>
#include <vector>
void getArray( int *c )
{
srand((int)time(0));
for(int i=0; i<20; i++)
{
c[i] = rand()%100;
}
}
void insertC( const int a, std::vector<int> &c , int right )
{
int left = 0;
if (right == 0)
{
c.push_back(a);
return;
}
//从大到小
int mid = 0;
right = right - 1;
while (left <= right)
{
mid = (left + right)/2;
if (a > c[mid])
{
right = mid-1;
}
else
{
left = mid+1;
}
}
c.insert(c.begin() +left, 1, a);
return;
}
void insertAB( int *a, int *b, std::vector<int>& c )
{
int he1 = 0;
int he2 = 0;
int aIndex = 0;
int bIndex = 0;;
for (int i = 0 ; i < 20; i++)
{
if(he1 < he2)
{
a[aIndex++] = c[i];
he1 += c[i];
}
else
{
b[bIndex++] = c[i];
he2 += c[i];
}
if(aIndex == 10)
{
for (int j = bIndex; bIndex <10; bIndex++)
{
b[bIndex++] = c[++i];
}
std::cout<<"和:"<<he1<<" "<<he2 <<std::endl;
return;
}
if(bIndex == 10)
{
for (int j = aIndex; aIndex <10; aIndex++)
{
b[aIndex++] = c[++i];
}
std::cout<<"和:"<<he1<<" "<<he2 <<std::endl;
return;
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[10],b[10];
//int c[20];
std::vector<int> c;
//随机取值
getArray(a);
getArray(b);
int right = 0;
//sort
for (int i = 0; i < 10; i++)
{
insertC(a[i], c, right);
right++;
}
for (int i = 0; i < 10; i++)
{
insertC(b[i], c , right);
right++;
}
//分别插入
insertAB(a, b, c);
for (int i = 0; i < 10; i++)
{
std::cout<<a[i]<<" "<<b[i]<<std::endl;
}
system("PAUSE");
return 1;
}