繁体   English   中英

选择每个数组中一半元素的两个数组的最小总和

[英]Minimum sum of two arrays choosing half of the elements in each

您好,我不是所谓的专业程序员。 我有两个数组a1a2integer s 具有相同的偶数长度n 我需要通过为每个索引选择一个元素来找到a1a2中元素的最小总和,所选元素的一半应位于 a1 中,其余位于 a2 中。

示例

 a1 = [36, 72];  
 a2 = [35, 61];

结果应该是97因为我们应该从a1选择36 ,从a2选择61 我认为一种解决方案是选择a1a2所有可能的n/2元素并计算它们的结果。 能否找到更有效的解决方案?

让我们表示数组a1a2

    a1 = [36, 72];  
    a2 = [35, 61];

以不同的方式:我们结合第 i 个索引并计算penalty = a2[i] - a1[i]

    a = [(36, 35; penalty = -1), (72, 61; penalty = -11)]

这里的penalty是当我们选择a2值而不是a1时我们必须付出的代价。 让我们按惩罚排序

    a = [(72, 61; penalty = -11), (36, 35; penalty = -1)]

现在让我们选择惩罚最低的n/2项并取a2项; 选择惩罚最高的n/2项并取a1项:

    a = [(72, 61; penalty = -11), (36, 35; penalty = -1)]
         (72, 61; penalty = -11) - lowest,  take a2 item - 61
         (36, 35; penalty = -1)  - highest, take a1 item - 36

时间复杂度是O(n * log(n)) - 排序。

C#实现:

  using System.Linq;

  ...

  int[] a1 = new int[] { 36, 72 };
  int[] a2 = new int[] { 35, 61 };

  var result = Enumerable
    .Range(0, a1.Length)
    .Select(i => new {
      v1 = a1[i],
      v2 = a2[i],
    })
    .OrderByDescending(item => item.v1 - item.v2)
    .Select((item, index) => index >= a1.Length / 2 
       ? item.v1 
       : item.v2)
    .Sum();

  Console.WriteLine(result);

结果:

  97

选择所有可能的 n/2 个元素并寻找最小值是可行的,但成本非常高。 特别是运行时复杂度将是 O(n^n)。

基本思想是,您希望选择索引 i 处具有高差异|a1[i] - a2[i]|元素。 . 所以这是一个算法的草图:

  1. 构建一个新数组 d,其中d[i] = |a1[i] - a2[i]|
  2. 现在按d降序获取索引i 因此,在最大的元素的索引d第一在随后的第二大元素的索引d等。
  3. 对于您从步骤 2 中获得的每个索引i 。取a1[i]a2[i]较小的元素并将其添加到您的总和中。 您还将跟踪从a1了多少元素以及从a2了多少元素。 如果您在某一时刻取了n/2 ,则用另一个数组中的剩余条目填充总和。

例子:

a1 = [11, 12, 13, 12]

a2 = [15, 2,  30, 14]

d  = [4 , 10, 17, 2]

所以这里首先选择 a1[2] (13) 因为 d[2] 是 d 中最大的元素并且 a1[2] < a2[2]。 接下来选择 a2[1] (2),因为 d[1] 是 d 中的第二大元素。 接下来你选择 a1[0] (11) 因为和之前一样的推理。 最后,您意识到您已经从 a1 中选择了两个元素,这就是为什么要将 a2 中的所有剩余元素添加到总和 (14) 中的原因。 结果是 13 + 2 + 11 + 14 = 40

当有效实施时,这可以在 O(n log n) 中运行

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM