Я можу це зробити в O (n). Дайте мені знати, коли ви хочете відповіді. Зауважте, що це включає просто проходження масиву один раз без сортування тощо. Я також повинен зазначити, що він використовує комутативність додавання і не використовує хешів, а витрачає пам'ять.
використання системи; використовуючи 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();
}
}
}