您的位置:首页 > 职场人生

华为面试题。。。。

2006-12-02 15:23 183 查看
传说这是一道华为的面试题。。。。

/*******************************************************************

文件名: MinDifference(***G).cpp
问题描述: 有两个数组a、b,大小都为n,数组元素的值任意,无序;
通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小,
最后输出两个数组和数组元素和的差值
解决思路:采用动态规划思想。先求出一个规划目标的模糊值***G,表示“完美”的a与b的
情况:a的元素和sa与b的元素和sb相等,并都等于***G。然后重置a与b:交换
a与b中的元素,另a中存有最小的n个元素(此时sa必然大于***G)。b中存有
最大的n个元素(此时sb必然大于***G);
开始进行“完美逼近”规划:在一次a[k]与b[0...n-1]的循环中进行交换,使
得此时的sa逼近***G(此时的sb也在逼近***G)。在此过程中,如果sa与***G相
等,这就产生了“完美”数组a与b,保证sa与sb的差值为0。如果到a[n-1]
时sa与***G不等,不过此时的数组a和b已经能保证sa与sb的差值最小了
正确性证明:(用反证法易证之)
时间复杂度分析:O(n^2)
关键步骤:Step 0:合并数组a和b到数组c,并对c按升序排序;
Step 1:求出数组c元素的和,除以2,其值为***G;
Step 2:将数组c里前n个数设置为数组a,后n个数设置为数组b,
并分别求出a元素与b元素的和,放入sa和sb;
Step 3:设置整型计数器 i = 0;
Step 4:a[i]与b[n-i-1]对换,并计算此时的sa与sb;//(试探)
Step 5:如果sa大于***G,a[i]与b[n-i-1]并重新算计sa与sb;//(回溯)
Step 6:否则(sa小于***G时)分别按升序排序a和b;
Step 7:i++;
Step 8:如果 i < n,执行Step 4;
Step 9:一次“逼近”过程结束;
开发平台: Win Xp SP2
编译环境: CL.exe 8.0 (in Visual Studio 2005 SDK)
作者: 88250
完成日期: 2006-11-26 版本: 2.0
修改之处:1. 修正了算法设计思想的描述:将贪心+回溯改为动态规划
2. 修正了存在重复比较数组a和b元素的问题,大大提高了处理效率
3. 可以从负值到正值地设定了数组元素的随机范围
Blog: http://DL88250.ynutx.net
E-mail: DL88250@gmail.com
QQ: 845765 or 316281008

*******************************************************************/

#i nclude <ctime>
#i nclude <vector>
#i nclude <algorithm> // 使用快速排序
#i nclude <iterator>
#i nclude <iostream>
#define TEST 0 // 测试开关

using namespace std;
// 全局数组描述:
const int num_max = 100; // 最大数组容量
const int range_min = -10; // 给定数组元素的最小值
const int range_max = 10; // 给定数组元素的最大值
vector<int> a; // 数组a
vector<int> b; // 数组b
vector<int> c; // 数组c
int average = 0; // 即算法描述中的***G
int sa = 0, sb = 0; // 分别保存数组a和b元素的和
int sum_difference = 0; // 存放数组a和b的差值的绝对值

// 全局函数描述:
// 对数组v进行随机初始化
void init(vector<int> &v);
// 显示数组v
void display(const vector<int> &v);
// 对数组v的元素求和放到sum里
void sum(const vector<int> &v, int &sum);
// 合并数组v到c中
void merge(const vector<int> &v, vector<int> &c);
// 设置数组a的元素
void set_a(void);
// 设置数组b的元素
void set_b(void);
// 交换a与b的值
void exchange(int &a, int &b);
// 一次贪心的过程,产生符合条件的数组a和b
// 返回这次贪心能产生的差值
int kernel(int &k);
// 输出当前的数组a和b与相应和及差值
void outCurrent(void);

// 主程序入口
int main(int argc, char* argv[])
{
// 设置随机种子
srand((unsigned)time(NULL));

init(a);
init(b);
sum(a, sa);
sum(b, sb);
outCurrent();

if (0 == sum_difference)
{// 就是最优解,不需要处理了,收工~ :-p
cout << endl << endl << "Okey! " << endl;
outCurrent();

return 0;
}

// Step 0
merge(a, c); merge(b, c);
sort(c.begin(), c.end());
#if TEST // 测试合并结果
cout << "c:"; display(c);
#endif
vector<int> cpy_a;
vector<int> cpy_b;
int tmp_sum_diff = sum_difference, sum_difference = 0;

cpy_a.assign(a.begin(), a.end());
cpy_b.assign(b.begin(), b.end());

// Step 1
average = (sa + sb) / 2;

// Step 2
set_a(); sum(a, sa);
set_b(); sum(b, sb);

// 进行***G“逼近”
for (int k = 0; k < num_max; k++)
{
sum_difference = kernel(k);
if (tmp_sum_diff > sum_difference)
{
cpy_a.clear(); cpy_b.clear();
tmp_sum_diff = sum_difference;
cpy_a.assign(a.begin(), a.end());
cpy_b.assign(b.begin(), b.end());
}

if (0 == tmp_sum_diff)
{// 找到“完美”解,直接结束过程
k = num_max;
}
}

if (tmp_sum_diff < sum_difference)
{
a.clear(); b.clear();
a.assign(cpy_a.begin(), cpy_a.end());
b.assign(cpy_b.begin(), cpy_b.end());
sum(a, sa); sum(b, sb);
sum_difference = tmp_sum_diff;
}

// 最优结果输出
cout << endl << endl << "Okey! " << endl;
outCurrent();
cout << "The runtime of this program: "
<< (float)clock() / CLK_TCK << 's' << endl;

return 0;
}

int kernel(int &k)
{
for (int i = 0; i < num_max; i++)
{
#if TEST // 测试当前数组a和b的值及相应和的情况
cout << endl << "TEST:" << endl;
outCurrent();
cout << "END TEST" << endl;
#endif
// Step 4(试探)
exchange(a[k], b[num_max-i-1]);
sum(a, sa); sum(b, sb);

if (sa > average) // Step 5(回溯)
{
exchange(a[k], b[num_max-i-1]);
sum(a, sa); sum(b, sb);
}
else if (sa < average) // Step 6
{
sort(a.begin(), a.end());
sort(b.begin(), b.end());
break;
}
else
{// 发现“完美”解
break;
}
}

return sum_difference = abs(sa - sb);
}

void outCurrent(void)
{
cout << "a:"; display(a);
cout << "b:"; display(b);
cout << "Sum a: " << sa << endl;
cout << "Sum b: " << sb << endl;
sum_difference = abs(sa - sb);
cout << "The difference of a'sum and b'sum: "
<< sum_difference << endl;

return;
}

void init(vector<int> &v)
{
for (int i = 0; i < num_max; i++)
{
v.push_back((((double)rand() /
(double)RAND_MAX) * range_max + range_min));
}

return;
}

void display(const vector<int> &v)
{

for (vector<int>::const_iterator
i = v.begin();
i != v.end();
i++)
{
cout << ' ' << *i;
}
cout << endl;

return;
}

void sum(const vector<int> &v, int &sum)
{
sum = 0;

for (vector<int>::const_iterator
i = v.begin();
i != v.end();
i++)
{
sum += *i;
}

return;
}

void merge(const vector<int> &v, vector<int> &c)
{
for (vector<int>::const_iterator
i = v.begin();
i != v.end();
i++)
{
c.push_back(*i);
}

return;
}

void set_a(void)
{
a.clear();

for (int i = 0; i < num_max; i++)
{
a.push_back(c[i]);
}

return;
}

void set_b(void)
{
b.clear();

for (int i = num_max; i < 2 * num_max; i++)
{
b.push_back(c[i]);
}

return;
}

void exchange(int &a, int &b)
{
int tmp = a;

a = b;
b = tmp;

return;
}

现在效率不错了,呵呵。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: