Я могу сделать это за O (n). Дай мне знать, когда захочешь получить ответ. Обратите внимание, что он включает в себя простой однократный обход массива без сортировки и т. Д. Я также должен упомянуть, что он использует коммутативность сложения и не использует хеши, но тратит впустую память.
используя Систему; using System.Collections.Generic;
/ * Существует подход O (n) с использованием таблицы поиска. Подход состоит в том, чтобы сохранить значение в «бункере», который можно легко найти (например, O (1)), если оно является кандидатом на соответствующую сумму.
например,
для каждого a [k] в массиве мы просто помещаем его в другой массив в позицию x - a [k].
Предположим, что у нас есть [0, 1, 5, 3, 6, 9, 8, 7] и x = 9
Создаем новый массив,
значение индексов
9 - 0 = 9 0
9 - 1 = 8 1
9 - 5 = 4 5
9 - 3 = 6 3
9 - 6 = 3 6
9 - 9 = 0 9
9 - 8 = 1 8
9 - 7 = 2 7
ТОГДА важны только те значения, которые имеют индекс в новой таблице.
Итак, скажем, когда мы достигаем 9 или равного числа, мы видим, имеет ли наш новый массив индекс 9-9 = 0. Поскольку он знает, что все содержащиеся в нем значения прибавятся к 9. (обратите внимание, что в этом случае очевидно, что есть только 1 возможный, но в нем может быть несколько значений индекса, которые нам нужно сохранить).
Таким образом, фактически нам нужно всего лишь один раз пройти через массив. Поскольку сложение коммутативно, мы получим все возможные результаты.
Например, когда мы дойдем до 6, мы получим индекс в нашей новой таблице как 9 - 6 = 3. Поскольку таблица содержит это значение индекса, мы знаем значения.
По сути, это обмен скорости на память. * /
namespace sum
{
class Program
{
static void Main(string[] args)
{
int num = 25;
int X = 10;
var arr = new List<int>();
for(int i = 0; i <= num; i++) arr.Add((new Random((int)(DateTime.Now.Ticks + i*num))).Next(0, num*2));
Console.Write("["); for (int i = 0; i < num - 1; i++) Console.Write(arr[i] + ", "); Console.WriteLine(arr[arr.Count-1] + "] - " + X);
var arrbrute = new List<Tuple<int,int>>();
var arrfast = new List<Tuple<int,int>>();
for(int i = 0; i < num; i++)
for(int j = i+1; j < num; j++)
if (arr[i] + arr[j] == X)
arrbrute.Add(new Tuple<int, int>(arr[i], arr[j]));
int M = 500;
var lookup = new List<List<int>>();
for(int i = 0; i < 1000; i++) lookup.Add(new List<int>());
for(int i = 0; i < num; i++)
{
// Check and see if we have any "matches"
if (lookup[M + X - arr[i]].Count != 0)
{
foreach(var j in lookup[M + X - arr[i]])
arrfast.Add(new Tuple<int, int>(arr[i], arr[j]));
}
lookup[M + arr[i]].Add(i);
}
for(int i = 0; i < arrbrute.Count; i++)
Console.WriteLine(arrbrute[i].Item1 + " + " + arrbrute[i].Item2 + " = " + X);
Console.WriteLine("---------");
for(int i = 0; i < arrfast.Count; i++)
Console.WriteLine(arrfast[i].Item1 + " + " + arrfast[i].Item2 + " = " + X);
Console.ReadKey();
}
}
}