Eu posso fazer isso em O (n). Deixe-me saber quando você quer a resposta. Note que envolve simplesmente percorrer o array uma vez sem classificação, etc ... Devo mencionar também que ele explora a comutatividade da adição e não usa hashes, mas desperdiça memória.
using System; using System.Collections.Generic;
/ * Existe uma abordagem O (n) usando uma tabela de pesquisa. A abordagem é armazenar o valor em uma "lixeira" que possa ser facilmente pesquisada (por exemplo, O (1)) se for um candidato a uma soma apropriada.
por exemplo,
para cada a [k] na matriz, simplesmente a colocamos em outra matriz no local x - a [k].
Suponha que temos [0, 1, 5, 3, 6, 9, 8, 7] e x = 9
Criamos uma nova matriz,
valor dos índices
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
ENTÃO, os únicos valores que importam são os que possuem um índice na nova tabela.
Então, digamos que quando atingirmos 9 ou igual, veremos se nossa nova matriz possui o índice 9 - 9 = 0. Como sabemos que todos os valores que ela contém serão adicionados a 9. (observe que nessa causa é óbvio que há apenas 1 possível, mas pode ter vários valores de índice que precisamos armazenar).
Então, efetivamente, o que acabamos fazendo é ter que passar pelo array apenas uma vez. Como a adição é comutativa, teremos todos os resultados possíveis.
Por exemplo, quando chegamos a 6, obtemos o índice em nossa nova tabela como 9 - 6 = 3. Como a tabela contém esse valor de índice, conhecemos os valores.
Isso é basicamente trocar a velocidade pela memória. * /
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();
}
}
}