O (n)에서 할 수 있습니다. 답을 원하면 알려주세요. 정렬하지 않고 배열을 한 번만 순회하는 것을 포함합니다. 추가의 교환 성을 이용하고 해시를 사용하지 않지만 메모리를 낭비한다는 점도 언급해야합니다.
시스템 사용; System.Collections.Generic 사용;
/ * 조회 테이블을 사용하는 O (n) 접근 방식이 있습니다. 접근 방식은 값이 적절한 합계의 후보 인 경우 쉽게 조회 할 수있는 "bin"(예 : 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에 추가된다는 것을 알고 있기 때문에 (이 원인에서는 하나는 가능하지만 저장해야하는 여러 인덱스 값이있을 수 있습니다.)
따라서 효과적으로 우리가하는 일은 어레이를 한 번만 이동하면됩니다. 덧셈은 교환 적이기 때문에 가능한 모든 결과를 얻을 수 있습니다.
예를 들어, 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();
}
}
}