有两个数组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[i] - b[j]

只有当|A-2x|<|A|,调换a[i]和b[j]才有意义,此时的条件为:

0<x<A,A>0或者A<x<0,A<0,如果找不符合这样条件的x,则结束调换。

并且当x越接近A/2,效果越好(A‘趋近于0)。

所以算法大概如下:

在a和b中寻找两个数a[i],b[j]使得0<x<A,A>0或者A<x<0,A<0,并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到符合0<x<A,A>0或者A<x<0,A<0的a[i],b[j]为止。

代码如下:

#include<iostream>
using namespace std;
void minSumDiff(int a[],int b[],int n)
{
    bool unfinish=true;
    while(unfinish)
    {
        unfinish=false;
        int sumDiffab=0;//存储sum(a)-sum(b)=A
        for(int i=0;i<n;i++)
            sumDiffab+=a[i]-b[i];
        float halfSum=sumDiffab/2.0;//即A/2
        int posa=0,posb=0;
        float mindis=abs(sumDiffab);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                int x=a[i]-b[j];
                if((sumDiffab>0&&x>0&&x<sumDiffab)||(sumDiffab<0&&x<0&&x>sumDiffab))//if(x*sumDiffab>0&&abs(x)<abs(sumDiffab))
                    //只有满足|A-2x|<|A|,调换才有意义:即A>0时,0<x<A;当A<0时,A<x<0
                {
                    unfinish=true;
                    float t=abs(x-halfSum);//计算x与A/2的距离
                    if(t<mindis)//存储离A/2最近的x的距离值以及对应的调换。
                    {
                        mindis=t;
                        posa=i;
                        posb=j;
                    }
                }
            }
        }
        if(unfinish)
        {
            int tmp;
            tmp=a[posa];
            a[posa]=b[posb];
            b[posb]=tmp;
        }
    }
}
int main()
{
    int a[]={4,3,9};
    int b[]={2,1,6};
    minSumDiff(a,b,3);
    for(int i=0;i<3;i++)
    {
        cout<<a[i]<<","<<b[i]<<endl;
    }
    system("pause");
    return 0;
}
时间: 2024-10-10 02:31:38

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

【编程题目】有两个序列 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元素的和]之间的差最小_利用排列组合思路解决_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

有两个数组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

说明如何用一个数组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 实现,晚些时候 上代码吧~

程序员面试题目总结--数组(三)【旋转数组的最小数字、旋转数组中查找指定数、两个排序数组所有元素中间值、数组中重复次数最多的数、数组中出现次数超过一半的数】

转!http://blog.csdn.net/dabusideqiang/article/details/38271661 11.求旋转数组的最小数字 题目:输入一个排好序的数组的一个旋转,输出旋转数组的最小元素. 分析:数组的旋转:把一个数组最开始的若干个元素搬到数组的末尾.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1.这道题最直观的解法并不难.从头到尾遍历数组一次,就能找出最小的元素,时间复杂度显然是O(N).但这个思路没有利用输入数组

编程算法 - 将排序数组按绝对值大小排序 代码(C)

将排序数组按绝对值大小排序 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 排序的数组有可能包含正负, 可以使用折半查找确定中值位置, 然后再使用两个指针, 顺次排序两端. 解决思路是: 1.数组中的元素全为正,返回: 2.数组中的元素全为负,返回: 3.数组中有正数有负数,就用二分法查找,判断中间元素的符号 a)中间元素为正,继续判断中间元素前面一个元素的符号; b)中间元素为负,判断中间元素后一个元素的符号; c)中间元素为零,令其等于结果值返

找出一组数中只出现一次的两个数,其他所有数都是成对出现的

题目: 给一组数,只有两个数只出现了一次,其他所有数都是成对出现的.怎么找出这两个数.编写函数实现. 题目分析: 上次介绍了,对于一组数中只有一个数只出现一次,其他所有数都是成对出现的,我们采用了对全部数组元素进行异或,但是对于找出两个出现一次的数应该怎么解决呢?先对所有的元素进行异或,则结果为两个出现一次的数的异或结果,然后将结果转换为二进制,找出二进制数中的第一个1,然后根据这个1的判断条件进行分组,分为两组,分别对两个组的元素进行全部异或,则就找出两个不同的数. 例如:数组中的元素为下面这

聊聊JVM(三)两种计算Java对象大小的方法

这篇说说如何计算Java对象大小的方法.之前在聊聊高并发(四)Java对象的表示模型和运行时内存表示 这篇中已经说了Java对象的内存表示模型是Oop-Klass模型. 普通对象的结构如下,按64位机器的长度计算 1. 对象头(_mark), 8个字节 2. Oop指针,如果是32G内存以下的,默认开启对象指针压缩,4个字节 3. 数据区 4.Padding(内存对齐),按照8的倍数对齐 数组对象结构是 1. 对象头(_mark), 8个字节 2. Oop指针,如果是32G内存以下的,默认开启对

写一函数,调整数组使奇数全部都位于偶数前面

调整数组使奇数全部都位于偶数前面.  输入一个整数数组,实现一个函数,  来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分, 所有偶数位于数组的后半部分. 1 #include<stdio.h> 2 3 #define NUM 10 4 5 void Change_num(int* start, int* end) 6 { 7 //开头找偶数,结尾找奇数,找到后两个相互交换位置 8 //1,2,3,4,5,6,7,8,9,5 9 //1, 3, 5, 4, 5, 6, 7, 8,