zoukankan      html  css  js  c++  java
  • IT公司100题-32-交换元素,使数组差最小

    问题描述:
    有两个整数序列a, b,大小都为n, 序列元素的值任意整数,无序。
    要求:通过交换a, b 中的元素,使得sum(a)-sum(b),差最小。
    例如:
    var a=[80, 40, 60, 10, 20, 30];
    var b=[10, 20, 50, 40, 30, 20];
     
    分析:
    近似最优算法:
    当前数组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-2x,只要 0 < x <= A/2,则A’ < A。
    所以,目标就是寻找i和j,使得x在0和A/2之间,并且越接近A/2越好。直到找不到这样的x为止。

    代码实现:

     1 // 32.cc
     2 #include <iostream>
     3 using namespace std;
     4 
     5 // 计算数组的和
     6 int sum(const int* a, int n) {
     7     int count = 0;
     8     for (int i = 0; i < n; i++)
     9         count += a[i];
    10     return count;
    11 }
    12 
    13 // 交换数组元素得到平衡集
    14 void balance_swap(int* a, int* b, int n) {
    15     // a指向和比较大的集合
    16     if (sum(a, n) < sum(b, n)) {
    17         int* t = a;
    18         a = b;
    19         b = t;
    20     }
    21 
    22     bool loop = true;
    23     while (loop) {
    24         loop = false;     
    25         for (int i = 0; i < n; i++) {
    26             for (int j = 0; j < n; j++) {
    27                 int diff = a[i] - b[j];
    28                 int A = sum(a, n) - sum(b, n);
    29                 if (diff > 0 && diff < A / 2) {
    30                     loop = true;
    31                     int tmp = a[i];
    32                     a[i] = b[j];
    33                     b[j] = tmp;
    34                 }
    35             }
    36         }
    37     }
    38 }
    39 
    40 // 打印数组元素
    41 void print(const int* a, int n) {
    42     for (int i = 0; i < n; i++)
    43         cout << a[i] << " ";
    44     cout << endl;
    45 }
    46 
    47 int main() {
    48     int a[] = {80, 40, 60, 10, 20, 30};
    49     int b[] = {10, 20, 50, 40, 30, 20};
    50     int n = sizeof(a) / sizeof(int);
    51 
    52     balance_swap(a, b, n);
    53 
    54     print(a, n);
    55     print(b, n);
    56 
    57     return 0;
    58 }

    输出:

    $ ./a.exe
    50 40 60 10 20 30
    10 20 80 40 30 20
  • 相关阅读:
    Zabbix监控mysql配置及故障告警配置
    Tesseract-OCR 字符识别---样本训练
    Wex5案例使用JSON传输Thinkphp后端对接,以达成数据正常输出
    Linux内核分析:recv、recvfrom、recvmsg函数实现
    libevent源码分析:evmap_io_active_函数
    libevent源码分析:epoll后端实现
    监听套接字不可写?
    Linux内核分析:dup、dup2的实现
    Linux内核分析:打开文件描述符实现
    libevent源码分析:http-server例子
  • 原文地址:https://www.cnblogs.com/dracohan/p/3949099.html
Copyright © 2011-2022 走看看