[英]Minimum sum of two arrays choosing half of the elements in each
您好,我不是所谓的专业程序员。 我有两个数组a1
和a2
的integer
s 具有相同的偶数长度n
。 我需要通过为每个索引选择一个元素来找到a1
和a2
中元素的最小总和,所选元素的一半应位于 a1 中,其余位于 a2 中。
示例:
a1 = [36, 72];
a2 = [35, 61];
结果应该是97
因为我们应该从a1
选择36
,从a2
选择61
。 我认为一种解决方案是选择a1
和a2
所有可能的n/2
元素并计算它们的结果。 能否找到更有效的解决方案?
让我们表示数组a1
和a2
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]|
元素。 . 所以这是一个算法的草图:
d[i] = |a1[i] - a2[i]|
d
降序获取索引i
。 因此,在最大的元素的索引d
第一在随后的第二大元素的索引d
等。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.