微软经典的算法面试100题之32题

探讨了两个无序整数序列通过交换元素使各自序列和的差最小的问题,采用合并排序及装包算法思想实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         在闲暇之余,无意之中看中感兴趣的一道算法,当时想了好久,没想出解决方案。于是想通过网络搜索一下该题的解决方案,然而搜索了很久没有检索到。可能是我花的时间太少了吧。虽然v_JULY_v的博客http://blog.youkuaiyun.com/v_july_v/article/category/823518有涉及到,且都已经已出书的形式发布了。然而我没有去购买该书,不清楚该书有没有解决。另外,v_JULY_v是我比较钦佩的人,其算法之道可谓是扎实。

         废话也说了太多了,还是回归主题吧!

         题目:

有两个序列a,b,大小都为n,序列元素的值任意整数,无序;
要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
例如:   
var a=[100,99,98,1,2, 3];
var b=[1, 2, 3, 4,5,40];

 

分析:

1. 通过交换a,b中的元素,说明a,b的元素个数一直没有变,且它们的元素个数相等。

 

思路:

1, 将其a,b序列合并一个序列c,并求出序列c的元素和sumc.

2, 从序列c中挑选n个元素组成一个序列a1,剩下的n个元素也就形成了b1序列。

那么如何挑选这n个元素,是有的标准的判断条件:就是a1序列中元素和尽可能的接近这个序列c的元素和的一半。那么就可以达到a,b序列元素和之差最小。

        如何挑选n个元素,我想到了“装包算法”。我之所以加上索引号,是因为我不清楚装包算法的定义,所以,姑且先称它为装包算法吧。

        想像一个情景,商店有12个产品a1.....a12,它们的价格分别为1、1、2、2、3、3、4、5、40、98、99、100。然而你身上只有179元((1+1+2+2+3+3+4+5+40+98+99+100)/ 2)。且商店要求你只能购买6个商品(是不是很奇葩的要求,姑且忍受吧,嘿嘿!!!)。那么你想把这钱尽可能的花完。你该如何挑选了?

        如果是人的,通过几次运算就可以得出要购买的商品为a5、a6、a7、a8、a9、a12。

        但是电脑不是人,是比较“笨”的机器。很多大牛都说过这句话。只有从电脑的角度想问题,才能理解电脑的奥秘。然而我们都是从人的角度出发想问题。废话多了,有点跑题了。

        回归主题,电脑是如何挑选的呢?

1,将12个产品按照价格进行从小到大排序。

2,选出前面6个产品。

3,计算选出的产品价格和,并与下一个产品的价格进行”加“运算。判断运算后的价格是否小于179元。如果是小于,跳到第4步。大于,跳到第五步。等于,就跳到第6步。

4,将价格最小的商品去掉,加上刚刚挑选的商品。然后跳到第3步。

5,计算超过了多少钱,然后将超过这个价钱中的最小价格的商品给去掉,然后加上给刚挑选的商品。接着跳到第3步。

6,已经挑选出最合适的6个商品。

        这个有个前提,每次新加上新商品,都要进行排序。

#include<stdio.h>
#include<stdlib.h>
/*
 * There are two sequence(a,b), and their size is n.
 * their element is arbitrary integer and that is unorder.
 * request:
 *  in order to get the result that absolute value which
 *  was from the distinction between the sum of a and the sum of b
 *  through exchanging elements
 *
 * example:
 *  var a = [100,99,98,1,2,3]
 *  var b = [1,2,3,4,5,40]
 * analysise:
 *  1. the size is not change.so I just can find the sum of six element
 *   is close the average.
 *
 * steps:
 *  1. merge two array into a array "c".
 *  2. order array.
 *  3. pack n element.
 */
int LENGTH=6;
void swap(int *a, int *b);
void print(int * a, int length);
void merge(int *a, int *b,int *c){
 int i = 0;
 int index = 0;
 for(;i<LENGTH;i++){
  c[index++] = a[i];
  c[index++] = b[i];
 }
}

void order(int *c,int length){
 int i = 0;
 for(;i < length-1 ; i++){
  int y = i+1;
  for(; y < length ;y++){
   if(c[i]>c[y])
    swap(&c[i],&c[y]); 
  }
 }
 print(c,length);
}
void swap(int * a, int * b){
 int tmp = *a;
 *a = *b;
 *b = tmp;
}
void print(int *array,int length){
 int i=0;
 printf("[");
 for(;i<length;i++){
  if(i!=length-1)
   printf("%d,",array[i]);
  else
   printf("%d]\n",array[i]);
 }
}
int sum(int *a,int length){
 int i=0;
 int sum = 0;
 for(;i<length;i++){
  sum += a[i];
 }
 return sum;
}
int *  pack(int * c,int* result){
 //int psize = length / 2;
 int average = sum(c,12) / 2;
 
 int i = 0;
 for(;i<6;i++){
  result[i]=c[i];
 }

 int sumres = sum(result,6);
 
 for(;i<2*LENGTH;i++){
  sumres = sum(result,6) + c[i];
  print(result,6);
  int dif = 0;
  if(sumres > average){
   dif = sumres - average;
   int k = 0;
   for(; k<6 ; k++){
    if(dif<result[k]){
     result[k] = c[i];
     break;
    }
   }
   order(result,6);
  }else if(sumres < average){
   result[0] = c[i];
   order(result,6);
  }else {
   return result;
  }
 }
 return result;
  
}
int main(){
 int a[6] = {100,99,98,1,2,3};
 int b[6] = {1,2,3,4,5,40};

 int * c = (int *) malloc(12*sizeof(int));
 merge(a,b,c); 
 order(c,12);
 
 int * result = (int *) malloc(LENGTH*sizeof(int));
 pack(c,result);
 
 printf("result:");
 print(result,6);
 return 0;
}

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值