Posso farlo in O (n). Fammi sapere quando vuoi la risposta. Nota che implica semplicemente attraversare l'array una volta senza ordinamento, ecc ... Devo anche menzionare che sfrutta la commutatività dell'aggiunta e non usa hash ma spreca memoria.
using System; using System.Collections.Generic;
/ * Esiste un approccio O (n) utilizzando una tabella di ricerca. L'approccio consiste nel memorizzare il valore in un "contenitore" che può essere facilmente consultato (ad esempio, O (1)) se è un candidato per una somma appropriata.
per esempio,
per ogni a [k] nell'array mettiamo semplicemente it in un altro array nella posizione x - a [k].
Supponiamo di avere [0, 1, 5, 3, 6, 9, 8, 7] e x = 9
Creiamo un nuovo array,
valore degli indici
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
ALLORA gli unici valori che contano sono quelli che hanno un indice nella nuova tabella.
Quindi, diciamo che quando raggiungiamo 9 o uguale vediamo se il nostro nuovo array ha l'indice 9 - 9 = 0. Dato che lo fa sappiamo che tutti i valori che contiene si aggiungeranno a 9. (nota in questo perché è ovvio che c'è solo 1 possibile ma potrebbe contenere più valori di indice che dobbiamo memorizzare).
Quindi, ciò che finiamo per fare è dover muoverci solo una volta attraverso l'array. Poiché l'aggiunta è commutativa, ci ritroveremo con tutti i risultati possibili.
Ad esempio, quando arriviamo a 6, inseriamo l'indice nella nostra nuova tabella come 9 - 6 = 3. Poiché la tabella contiene quel valore di indice, conosciamo i valori.
Questo è essenzialmente uno scambio di velocità con la memoria. * /
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();
}
}
}