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

时间:2017-12-15 10:29:10

标签: arrays algorithm

你好我不是一个所谓的专业程序员。我有两个a1a2 integer个数组,其中甚至长度 n。我需要通过选择每个索引一半的一个元素来找到a1a2中元素的最小总和所选元素的em>应位于a1中,其余元素位于a2中。

示例

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

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

2 个答案:

答案 0 :(得分:1)

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

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

  1. d[i] = |a1[i] - a2[i]|
  2. 中构建新数组d
  3. 现在按i的降序索取d索引。所以d中最大元素的索引首先是d中第二大元素的索引,依此类推。
  4. 对于您从第2步获得的每个索引i,请使用a1[i]a2[i]中较小的元素并将其添加到您的总和中。您还会跟踪从a1中获取的元素数量以及a2中的元素数量。如果您在某一时刻拿走了n/2,则填写总和,剩下的条目形成另一个数组。
  5. 示例:

    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)

    中运行

答案 1 :(得分:1)

让我们的数组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