Tôi có thể làm điều đó trong O (n). Hãy cho tôi biết khi bạn muốn câu trả lời. Lưu ý rằng nó chỉ liên quan đến việc duyệt qua mảng một lần mà không cần sắp xếp, v.v. Tôi cũng nên đề cập rằng nó khai thác tính giao hoán của phép cộng và không sử dụng hàm băm nhưng lãng phí bộ nhớ.
sử dụng Hệ thống; sử dụng System.Collections.Generic;
/ * Có một cách tiếp cận O (n) bằng cách sử dụng một bảng tra cứu. Cách tiếp cận là lưu trữ giá trị trong một "thùng" có thể dễ dàng tra cứu (ví dụ: O (1)) nếu nó là ứng cử viên cho một tổng thích hợp.
ví dụ,
đối với mỗi a [k] trong mảng, chúng ta chỉ cần đặt nó vào một mảng khác tại vị trí x - a [k].
Giả sử chúng ta có [0, 1, 5, 3, 6, 9, 8, 7] và x = 9
Chúng tôi tạo một mảng mới,
giá trị chỉ mục
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
THÌ các giá trị duy nhất quan trọng là những giá trị có chỉ mục trong bảng mới.
Vì vậy, giả sử khi chúng ta đạt đến 9 hoặc bằng, chúng ta sẽ xem liệu mảng mới của chúng ta có chỉ số 9 - 9 = 0. Vì nó biết rằng tất cả các giá trị mà nó chứa sẽ thêm vào 9 (lưu ý trong lý do này rõ ràng là chỉ có 1 có thể có nhưng nó có thể có nhiều giá trị chỉ mục mà chúng ta cần lưu trữ).
Vì vậy, hiệu quả những gì chúng tôi làm cuối cùng là chỉ phải di chuyển qua mảng một lần. Bởi vì phép cộng có tính chất giao hoán, chúng tôi sẽ kết thúc với tất cả các kết quả có thể.
Ví dụ, khi chúng ta đến 6, chúng ta nhận được chỉ mục vào bảng mới của chúng ta là 9 - 6 = 3. Vì bảng chứa giá trị chỉ số đó nên chúng ta biết các giá trị.
Đây thực chất là đánh đổi tốc độ cho bộ nhớ. * /
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();
}
}
}