Mogę to zrobić w O (n). Daj mi znać, kiedy chcesz otrzymać odpowiedź. Zauważ, że wymaga to po prostu jednokrotnego przejścia przez tablicę bez sortowania itp ... Powinienem również wspomnieć, że wykorzystuje przemienność dodawania i nie używa skrótów, ale marnuje pamięć.
using System; using System.Collections.Generic;
/ * Podejście O (n) istnieje przy użyciu tabeli przeglądowej. Podejście polega na przechowywaniu wartości w „koszu”, który można łatwo wyszukać (np. O (1)), jeśli jest kandydatem na odpowiednią sumę.
na przykład,
dla każdego a [k] w tablicy po prostu umieszczamy to w innej tablicy w lokalizacji x - a [k].
Załóżmy, że mamy [0, 1, 5, 3, 6, 9, 8, 7] i x = 9
Tworzymy nową tablicę,
wartość indeksów
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
WTEDY jedyne wartości, które mają znaczenie, to te, które mają indeks do nowej tabeli.
Powiedzmy, że kiedy osiągniemy 9 lub równe, zobaczymy, czy nasza nowa tablica ma indeks 9 - 9 = 0. Ponieważ wiemy, że wszystkie zawarte w niej wartości dodadzą się do 9. (zauważ, że w tym przypadku jest oczywiste, że jest tylko 1 możliwy, ale może zawierać wiele wartości indeksu, które musimy przechowywać).
W efekcie to, co ostatecznie robimy, to tylko jednokrotne przejście przez tablicę. Ponieważ dodawanie jest przemienne, otrzymamy wszystkie możliwe wyniki.
Na przykład, gdy dojdziemy do 6, otrzymujemy indeks do naszej nowej tabeli jako 9 - 6 = 3. Ponieważ tabela zawiera tę wartość indeksu, znamy wartości.
Zasadniczo polega to na zamianie szybkości na pamięć. * /
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();
}
}
}