Как уже обсуждалось в других ответах, лучшей стратегией будет всегда работать над двумя пунктами с минимальными затратами для каждой итерации. Таким образом, единственный оставшийся вопрос заключается в том, как эффективно брать два маленьких предмета каждый раз.
Поскольку вы просили о лучшей производительности, я бесстыдно взял алгоритм из NetMage и изменил его, чтобы ускорить его примерно на 40% для моего теста (спасибо и +1 к NetMage ).
Идея состоит в том, чтобы работать в основном на одном массиве.
Каждая итерация увеличивает начальный индекс на 1 и перемещает элементы в массиве, чтобы освободить место для суммы из текущей итерации.
public static long CostOfMerge2(this IEnumerable<int> psrc)
{
long total = 0;
var src = psrc.ToArray();
Array.Sort(src);
var i = 1;
int length = src.Length;
while (i < length)
{
var sum = src[i - 1] + src[i];
total += sum;
// find insert position for sum
var index = Array.BinarySearch(src, i + 1, length - i - 1, sum);
if (index < 0)
index = ~index;
--index;
// shift items that come before insert position one place to the left
if (i < index)
Array.Copy(src, i + 1, src, i, index - i);
src[index] = sum;
++i;
}
return total;
}
Я проверил следующий код вызова (переключение между CostOfMerge
и CostOfMerge2
), с несколькими различными значениями для случайного начального числа, числа элементов и максимального значения начальных элементов.
static void Main(string[] args)
{
var r = new Random(10);
var testcase = Enumerable.Range(0, 400000).Select(x => r.Next(1000)).ToList();
var sw = Stopwatch.StartNew();
long resultCost = testcase.CostOfMerge();
sw.Stop();
Console.WriteLine($"Cost of Merge: {resultCost}");
Console.WriteLine($"Time of Merge: {sw.Elapsed}");
Console.ReadLine();
}
Результат для показанной конфигурации для NetMage CostOfMerge:
Cost of Merge: 3670570720
Time of Merge: 00:00:15.4472251
My CostOfMerge2:
Cost of Merge: 3670570720
Time of Merge: 00:00:08.7193612
Конечно, подробные числа зависят от аппаратного обеспечения, и разница может быть больше или меньше в зависимости от загруженности.