华为面试题。。。。

来源:互联网 发布:ai平面设计软件 编辑:程序博客网 时间:2024/05/29 02:04

传说这是一道华为的面试题。。。。

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

   文件名: MinDifference(AVG).cpp
   问题描述: 有两个数组a、b,大小都为n,数组元素的值任意,无序;
             通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小,
             最后输出两个数组和数组元素和的差值
   解决思路:采用动态规划思想。先求出一个规划目标的模糊值AVG,表示“完美”的a与b的
             情况:a的元素和sa与b的元素和sb相等,并都等于AVG。然后重置a与b:交换
             a与b中的元素,另a中存有最小的n个元素(此时sa必然大于AVG)。b中存有
             最大的n个元素(此时sb必然大于AVG);
             开始进行“完美逼近”规划:在一次a[k]与b[0...n-1]的循环中进行交换,使
      得此时的sa逼近AVG(此时的sb也在逼近AVG)。在此过程中,如果sa与AVG相
      等,这就产生了“完美”数组a与b,保证sa与sb的差值为0。如果到a[n-1]
             时sa与AVG不等,不过此时的数组a和b已经能保证sa与sb的差值最小了
   正确性证明:(用反证法易证之)
   时间复杂度分析:O(n^2)
   关键步骤:Step 0:合并数组a和b到数组c,并对c按升序排序;
             Step 1:求出数组c元素的和,除以2,其值为AVG;
             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大于AVG,a[i]与b[n-i-1]并重新算计sa与sb;//(回溯)
             Step 6:否则(sa小于AVG时)分别按升序排序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;                // 即算法描述中的AVG
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);

        // 进行AVG“逼近”
        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;
}

现在效率不错了,呵呵。。。。

 

原创粉丝点击