有两个数组a,b,大小都为n,;通过交换a,b中的元素,使sum(a)-sum(b)最小。

有两个数组a,b,大小都为n,数组元素的值任意整形数,无序; 
要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小。

当前数组a和数组b的和之差为
    A = sum(a) - sum(b)

a的第i个元素和b的第j个元素交换后,a和b的和之差为
    A‘ = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
           = sum(a) - sum(b) - 2 (a[i] - b[j])
           = A - 2 (a[i] - b[j])
    设x = a[i] - b[j]

|A| - |A‘| = |A| - |A-2x|

假设A > 0,

当x 在 (0,A)之间时,做这样的交换才能使得交换后的a和b的和之差变小,x越接近A/2效果越好,

如果找不到在(0,A)之间的x,则当前的a和b就是答案。

所以算法大概如下:

在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。

int sum1,sum2,a;          //分别表示 a[]的和 b[]的和 以及2者之差
    int temp;
    bool dayu0;                  //和之差是否大于0
    int pos1,pos2;               //等待交换的a[i]和b[j]的下标 i j
    float minn;                //最接近a/2的a[i]-b[j]值
    bool have1 ;               //是否能有解
    while (1)
    {
        sum1 = 0;
        sum2 = 0;
        for (int i = 0 ; i < n;++i)             //求两个数组的和
        {
            sum1 += ar1[i];
            sum2 += ar2[i];
        }
        a = sum1 - sum2;                    //和之差
        dayu0 = a>0?true:false;                  //和之差是大于0还是小于0
        have1 = false;                           //是否能找到解
        for (int i = 0 ; i < n;++i)            //找最接近a/2的 a[i]-b[j]
        {
            for (int j = 0;j < n;++j)
            {
                temp = ar1[i] - ar2[j];
                if ((dayu0&&temp > 0&&temp < a)||(!dayu0&&temp < 0 && temp > a))      //如果a[i]-b[j] 在(0,a)之间  (超出的就没有意义了)
                {
                    if (have1&&abs(temp - a/2.0) < minn)                 //若比之前的a[i]-b[j]更接近a/2 则更新
                    {
                        minn = abs(temp - a/2.0);
                        pos1 = i;
                        pos2 = j;
                    }
                    else
                    {
                        have1 = true;
                        minn = abs(temp - a/2.0);
                        pos1 = i;
                        pos2 = j;
                    }
                }
            }
        }
        if (!have1)         //若找不到符合条件的a[i]-b[j]了 则结束
        {
            break;
        }
        swap(ar1[pos1],ar2[pos2]);       //交换a b中的元素
    }

  

时间: 2024-10-10 02:31:37

有两个数组a,b,大小都为n,;通过交换a,b中的元素,使sum(a)-sum(b)最小。的相关文章

有两个数组a,b,大小都为n,数组元素的值任意整形数,无序,通过交换a,b中的元素,使得|sum(a)-sum(b)|最小

有两个数组a,b,大小都为n,数组元素的值任意整形数,无序: 要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小. 令A=sum(a)-sum(b) a的第i个元素和b的第j个元素交换后,a和b的和之差为 A'= sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])           = sum(a) - sum(b) - 2 (a[i] - b[j])           = A - 2 (a[i] - b[j]) 设x = a[

[微软]有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小_利用排列组合思路解决_python版

(原题出自微软公司面试题)问题如下:有两个序列a,b,大小都为n,序列元素的值任意整数,无序:要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小.例如:a=[100,99,98,1,2, 3]b=[1, 2, 3, 4,5,40] 题目是看到QQ群友发的,网上也百度了下目前已经有好几种解法了.写了半天有点晕,后面忽然想到中学时候数学里面的排列组合的方法.方法对于较短的list可行,长list组合情况太多,可能耗时太长或溢出. 1 from itertools im

调整数组的中的元素使奇数位于数组的前面,偶数位于数组的后面

分为两部分的问题,最好只用两个指针. 譬如此题:就可以一个指针从头往后扫,而另一个指针从后往前扫,保证第一个指针永远指向奇数,最后一个指针永远指向偶数,然后两者交换,直至最终两个指针相等,即扫描完了所有的元素. 代码如下所示: 1 //调整数组顺序使奇数位于偶数前面 2 #include<iostream> 3 using namespace std; 4 void function1(int* number, unsigned int length) 5 { 6 int p1 = 0; 7

【编程题目】有两个序列 a,b,大小都为 n,序列元素的值任意整数,无序;(需要回头仔细研究)

32.(数组.规划)有两个序列 a,b,大小都为 n,序列元素的值任意整数,无序:要求:通过交换 a,b 中的元素,使[序列 a 元素的和]与[序列 b 元素的和]之间的差最小.例如: var a=[100,99,98,1,2,3];var b=[1,2,3,4,5,40]; 首先,目标一定是先找到n个数字,使得数字和比总和的一半小,但是最接近. 思路一:开始看这道题跟之前学的动态规划很像,就想用动态规划来解.但是....做不出来........... 必须要选一半的数字让我头都大了. 思路二:

交换两个数组的元素使之总和的差值最小

题目描述: 有两个数组a,b,大小都为n,数组元素的值任意整型数,无序: 要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小. #include "stdafx.h" #include <math.h> #include <time.h> #include <stdlib.h> void print_arr(int a[], int b[], int n) { printf("a: "); for (int

两个数组之间的引用

1 public class Demo{ 2 public static void main(String[] args){ 3 int[] arr1={1,2,4,8,16}; 4 int[] arr2; 5 arr2=arr1;//将数组一赋给数组二 是引用之间的赋值,表示两个数组引用同一个地址内存,只要有一个数组值改动,两个数组里的值都改动了 6 7 arr2[3]=1024;//通过数组2修改其中一个元素的值 8 9 //输出数组一的值 10 System.out.println("数组

75 int类型数组中除了一个数出现一次或两次以外,其他数都出现三次,求这个数。

[本文链接] http://www.cnblogs.com/hellogiser/p/single-number-of-array-with-other-three-times.html [题目] int类型数组中除了一个数出现一次或两次以外,其他数都出现三次,求这个数. [分析] C++ Code 123456789101112   int singleNumber(int *a, int n) {     int ones = 0, twos = 0;     for (int i = 0;

说明如何用一个数组A[1...n]来实现两个栈,使得两个栈中的元素总数不到n时,两者都不会发生上溢。注意PUSH和POP操作的时间应为O(1)。

校招开始了,发现自己数据结构,Algorithms的知识都还给老师了.喵了个呜的! <算法导论>开啃吧~ 从第三章数据结构开始吧~ 10.1-2 : 如何用一个数组A[1...n]来实现两个栈,使得两个栈中的元素总数不到n时,两者都不会发生上溢.注意PUSH和POP操作的时间应为O(1). 解:思想是,建一维数组,两个栈stack1和stack2分别从数组A[0]和A[N-1]开始push,栈指针相遇时,两个栈中元素总数为n. 在思考怎么用java 实现,晚些时候 上代码吧~

假设有两个数组,其中的元素都是数字,现在要对其排序

假设有 number,group,两个数组,其中的元素都是数字,现在要对其排序排序的规则如下: 1.如果 group里面元素,存在于numbers了里面 2.要把出现在 group 内的数字 放在 number 的那些数字之前,注意排序 numbers = [8, 3 ,1, 2, 5,4,7,6] group = {2,3,5,7} 分析了下,应该是优先级的问题,这里使用了元组排序的方法: numbers = [8, 3 ,1, 2, 5,4,7,6] group = {2,3,5,7} tm