O(n)でできます。いつ答えが欲しいか教えてください。並べ替えなしで配列を1回トラバースすることなどが含まれることに注意してください。また、加算の可換性を利用し、ハッシュを使用せず、メモリを浪費することにも言及します。
システムの使用; 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つの可能性がありますが、格納する必要のある複数のインデックス値が含まれている可能性があります)。
つまり、最終的には、アレイを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();
}
}
}