zoukankan      html  css  js  c++  java
  • 交换元素,使两数组之和的差最小 【微软面试100题 第三十二题】

    题目要求: 

      有两个序列a,b,大小都为n,序列元素的值任意整数,无序;

      要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。

      参考资料:程序员编程艺术(By July)

    题目分析:

      先求两个序列和之差diff;然后从a和b中分别取一个元素,利用公式:diff-a[i]+b[j]-(a[i]-b[j]) = diff-2*(a[i]-b[j])的绝对值和diff的绝对值比较,如果比diff的小,就更新diff,同时交换元素a[i]/b[j].

      过程中,有一个flag,是作为退出使用的。当两个for循环之后都没有交换的了,flag=0,就退出while。

      -------------------------------------------------------------------------------------

      核心代码分析:为什么会使用if((A[i]!=B[j]) && (abs(diff-2*(A[i]-B[j]))<=abs(diff)))...1,而不是if(abs(diff-2*(A[i]-B[j]))<abs(diff))...2 ,因为如果使用代码2,就会有特例出现:

        A = { 5,5,9,10 }; B ={ 4,7,7,13 }; A的和为29,B为31。当把A中的5,5与B中的4,7交换后,A与B的和都为30,差为0.但使用代码2将检测不到这种交换!因此输出结果是原数组。
      而使用代码1就可以输出差为0的两个数组。因为A和B和之差的绝对值为2,如果A的5与B的7交换后差的绝对值也是2,可以交换。则5和7交换之后,再把A的5和B的4交换,差的绝对值就为0了。
      为什么有(A[i]!=B[j]),因为如果A和B中有相同元素的时候,就会进入死循环。
      所以综合起来,就应该使用if((A[i]!=B[j]) && (abs(diff-2*(A[i]-B[j]))<=abs(diff)))
      -------------------------------------------------------------------------------------

    代码实现:

    #include <iostream>  
    #include <algorithm>
    #include <functional>
    
    using namespace std;
    
    #define N 5
    int A[N]={5,5,9,10,1};
    int B[N]={4,7,7,13,1};
    void Swap()
    {
        int sumA=0,sumB=0;
        int times = 0;
        int flag = 1;
        for (int i=0;i<N;i++)
        {
            sumA+=A[i];
            sumB+=B[i];
        }
    
        int diff=sumA-sumB;
        if(diff==0)
            return;
        while (flag)
        {
            flag = 0;
            for(int i=0;i<N;i++)
                for (int j=0;j<N;j++)
                {    
                    if((A[i]!=B[j]) && (abs(diff-2*(A[i]-B[j]))<=abs(diff)))
                    {
                        diff = diff-2*(A[i]-B[j]);
                        swap(A[i],B[j]);
                        flag = 1;
                    }
                    times++;
                }
        } 
        cout << "times = " << times << endl;
    }
    int main()
    {
        Swap();
        for( int i=0;i<N;i++)cout<<A[i]<< " ";
        cout<<endl;
        for( int i=0;i<N;i++)cout<<B[i]<< " ";
        cout<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    基础总结深入:数据类型的分类和判断(数据、内存、变量) 对象 函数 回调函数 IIFE 函数中的this 分号
    BOM 定时器 通过修改元素的类来改变css JSON
    事件 事件的冒泡 事件的委派 事件的绑定 事件的传播
    DOM修改 使用DOM操作CSS
    包装类 Date Math 字符串的相关的方法 正则表达式 DOM DOM查询
    数组 call()、apply()、bind()的使用 this arguments
    autocad 二次开发 最小包围圆算法
    win10 objectarx向导在 vs2015中不起作用的解决办法
    AutoCad 二次开发 jig操作之标注跟随线移动
    AutoCad 二次开发 文字镜像
  • 原文地址:https://www.cnblogs.com/tractorman/p/4063866.html
Copyright © 2011-2022 走看看