回 帖 发 新 帖 刷新版面

主题:“华为面试题!8分钟做出来”,我做的思路,大家帮看一下对不对,谢谢哈~!

原题:有两个数组a,b,大小都为n,数组元素的值任意,无序;
要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
原帖http://bbs.misuland.com/bbsstaticweb/bbs_bbsforumannounce1221209363477_2.html

我的答案:
我能想出来怎么做,不过我打字慢,8分钟打不出来!嘿嘿!

前边和大家想的都一样,也是计算出数组a和b的差值c,然后除以2再取整。
之后,再做一个循环过程:
    做一个由所有的a和b的元素差值生成的二维数组sub[i][j]。然后,遍历这个数组寻找和c差值最小的元素,交换数组a和b中的元素i和j。如果,sub[i][j]和c的差值小于或等于1,结束循环,否则,继续。

大家帮看看啊!谢谢了!有写代码快的,帮忙写出来验证一下,不胜感激啊 !

回复列表 (共24个回复)

11 楼

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//定义数组大小
#define SIZE 3
void InitArray(int* a, int* b, int size)
{
    srand((unsigned)time(NULL));
    for(int i=0;i<SIZE;i++) a[i] = rand()%20, b[i] = rand()%20;
}
void ShowArray(int* arr, int size)
{
    for(int i=0;i<size;i++) printf("%d\t", arr[i]);
    printf("\n");
}
int ChangeArray(int* a, int* b, int size, int diffsum)
{
    int res=1, i, j;
    for(i=0;i<size;i++)
        for(j=0;j<size;j++)
            if((a[i]-b[j]<diffsum)&&(a[i]-b[j]>0))
            {
                a[i]^=b[j]^=a[i]^=b[j];
                diffsum -= 2*(b[j]-a[i]);
                res = 0;
                if(diffsum<=0) return res;
            }
            return res;
}
void main(void)
{
    int a[SIZE], b[SIZE], SumOfA, SumOfB, EndFlag=0, i;
    InitArray(a, b, SIZE);
    printf("Init array is:\n");
    ShowArray(a,SIZE), ShowArray(b,SIZE);
    while(!EndFlag)
    {
        for(i=0,SumOfA=0,SumOfB=0;i<SIZE;i++) SumOfA+=a[i], SumOfB+=b[i];
        EndFlag = (SumOfA>SumOfB)?ChangeArray(a, b, SIZE, SumOfA-SumOfB):ChangeArray(b, a, SIZE, SumOfB-SumOfA);
    }
    printf("\nChanged array is:\n");
    ShowArray(a,SIZE), ShowArray(b,SIZE);
    
    for(i=0,SumOfA=0,SumOfB=0;i<SIZE;i++) SumOfA+=a[i], SumOfB+=b[i];
    printf("\nSum of A is: %d\nSum of B is: %d\n", SumOfA, SumOfB);
}

12 楼

[quote]假设数据为 1 2 3 3 4 5
那么只有以下几种分法:
1 2 3 | 3 4 5
1 2 4 | 3 3 5
1 2 5 | 3 3 4
1 3 3 | 2 4 5
1 3 4 | 2 3 5
1 3 5 | 2 3 4
1 4 5 | 2 3 3
[/quote]

怎么可以这么假设。。。。
那假设数据为1,2,3,4,5,。。。。。,99,100呢?

13 楼

#include <stdio.h>
void ShowArray(int* arr, int size)
{
    for(int i=0;i<size;i++) printf("%d\t", arr[i]);
    printf("\n");
}
int ChangeArray(int* a, int* b, int size, int diffsum)
{
    int res=1, i, j;
    for(i=0;i<size;i++)
        for(j=0;j<size;j++)
            if((a[i]-b[j]<diffsum)&&(a[i]-b[j]>0))
            {
                a[i]^=b[j]^=a[i]^=b[j];
                diffsum -= 2*(b[j]-a[i]);
                res = 0;
                if(diffsum<=0) return res;
            }
    return res;
}
void main(void)
{
    int a[] = {1, 2, 8, 5};
    int b[] = {1, 2, 3, 3};
    int i, SumOfA, SumOfB, EndFlag=0, SIZE=sizeof(a)/sizeof(a[0]);
    while(!EndFlag)
    {
        for(i=0,SumOfA=0,SumOfB=0;i<SIZE;i++) SumOfA+=a[i], SumOfB+=b[i];
        EndFlag = (SumOfA>SumOfB)?ChangeArray(a, b, SIZE, SumOfA-SumOfB):ChangeArray(b, a, SIZE, SumOfB-SumOfA);
    }
    ShowArray(a,SIZE), ShowArray(b,SIZE);
    for(i=0,SumOfA=0,SumOfB=0;i<SIZE;i++) SumOfA+=a[i], SumOfB+=b[i];
    printf("\nSum of A is: %d\nSum of B is: %d\ndifferent = %d\n", SumOfA, SumOfB, SumOfA-SumOfB);
}

14 楼

re woshiyun:
我明白你的算法了
1. 将 a中的每一个数 和 b中的每一个数 比较,如果交换他俩可以使得差值变小,那么就交换;
2. 每次交换后就重新做第一步
3. 如果一次遍历中没发现可以交换的数,则说明已经是最优了。

15 楼

会不会存在“交换每一个数都无法使得差值变小,但同时交换一组数据可以使得差值变小”的情况呢?
虽然我没有找到这样的事例,但我也没能证明这种情况不存在。

16 楼

你们都没有读懂题,这是面试题,不是竞赛.

第一要求只是交换两个数组的值.
第二并没有要求出最优解.

此题只是考一下解决问题的能力和对数组程的能力.
而且考官基本没有时间读你的程序.

基本评分标准是循环次数,一次循环80分,两个循环60分.程序有错相应扣分.
能解释清楚算法和语句的目的相应加分.

一次循环算法是这样

sum_a = 0; sum_b = 0;

for_each i in 0, n
  if (sum_a > sum_b) swap(a[i], b[i]); 
  sum_a += a[i]; sum_b += b[i];
end for_each

要知道只有半小时的时间做题,还有很多客观题.

17 楼

能问个问题么?
a[i]^=b[j]^=a[i]^=b[j];
这句什么意思?没看懂
不好意思啊

18 楼

先分析题目:
  
    1、首先,有两个数组,长度为n(很多数),值随即(不确定);
    2、要求是寻找两个数组之间差值最小;
    3、方法是由两个数组交换其中的元素,前提是交换的基础上进行的,而不是将两个数组中的元素完全打乱或者是重组。


个人意见:
    1、先将两个数组分别求和sum1和sum2;
    2、然后求出这两个数组和的差值(假设sum1>sum2,sum1-sum2=n1,n1=5);
    3、然后比较数组,开始交换元素:
       假设:
    a      1 2 3 4 5
    b      2 3 4 5 6
    
           2 2 3 4 5
           1 3 4 5 6
           n1=n1-1*2=3
         
           3 2 3 4 5
           1 2 4 5 6
           n1=n1-1*2=1
    4、如果差值的范围在-c<0<c(c为一个所有数间的最小差值)时,比较完成,或者是最坏的情况,进行过最大的循环(以上面为例进行过25次比较(n方))。

19 楼

好贴,顶一个

20 楼


这个问题好像没有哪位大侠搞定啊。
把这个问题贴出来是希望大家一起来讨论,跟是否是面试题有什么关系,用多长时间搞定也没有关系。关键是大家来讨论搞这个问题。

我来回复

您尚未登录,请登录后再回复。点此登录或注册