Viết chương trình (hoặc hàm) thể hiện bốn độ phức tạp thời gian O lớn phổ biến tùy thuộc vào cách nó được chạy. Trong bất kỳ hình thức nào, nó có một số nguyên dương N mà bạn có thể giả sử là ít hơn 2 31 .
Khi chương trình được chạy ở dạng ban đầu, nó sẽ có độ phức tạp không đổi . Đó là, độ phức tạp phải là Θ (1) hoặc tương đương, Θ (1 ^ N) .
Khi chương trình được đảo ngược và chạy nó sẽ có độ phức tạp tuyến tính . Nghĩa là, độ phức tạp phải là Θ (N) hoặc, tương đương, Θ (N ^ 1) .
(Điều này có ý nghĩa vìN^1
được1^N
đảo ngược.)Khi chương trình được tăng lên gấp đôi , tức là nối với chính nó, và chạy nó nên có mũ phức tạp, đặc biệt là 2 N . Đó là, độ phức tạp phải là Θ (2 ^ N) .
(Điều này có ý nghĩa vì2
in2^N
là gấp đôi1
in1^N
.)Khi chương trình được nhân đôi và đảo ngược và chạy, nó sẽ có độ phức tạp đa thức , cụ thể là N 2 . Đó là, độ phức tạp phải là Θ (N ^ 2) .
(Điều này có ý nghĩa vìN^2
được2^N
đảo ngược.)
Bốn trường hợp này là những trường hợp duy nhất bạn cần xử lý.
Lưu ý rằng để chính xác, tôi đang sử dụng ký hiệu theta () lớn thay vì chữ O lớn vì thời gian chạy của các chương trình của bạn phải được giới hạn ở cả trên và dưới bởi độ phức tạp bắt buộc. Nếu không, chỉ cần viết một hàm trong O (1) sẽ thỏa mãn cả bốn điểm. Nó không quá quan trọng để hiểu sắc thái ở đây. Chủ yếu, nếu chương trình của bạn đang thực hiện các hoạt động k * f (N) cho một số k không đổi thì có khả năng là trong (f (N)).
Thí dụ
Nếu chương trình ban đầu là
ABCDE
sau đó chạy nó sẽ mất thời gian liên tục. Đó là, cho dù đầu vào N là 1 hoặc 2147483647 (2 31 -1) hoặc bất kỳ giá trị nào ở giữa, nó sẽ chấm dứt trong khoảng thời gian gần như nhau.
Phiên bản đảo ngược của chương trình
EDCBA
nên mất thời gian tuyến tính theo N. Đó là thời gian cần thiết để chấm dứt tỷ lệ xấp xỉ với N. Vì vậy, N = 1 mất ít thời gian nhất và N = 2147483647 mất nhiều thời gian nhất.
Phiên bản nhân đôi của chương trình
ABCDEABCDE
nên mất hai-to-the-N lần về N. Đó là, thời gian cần thiết để chấm dứt nên xấp xỉ tỉ lệ với 2 N . Vì vậy, nếu N = 1 chấm dứt trong khoảng một giây, N = 60 sẽ mất nhiều thời gian hơn tuổi của vũ trụ để chấm dứt. (Không, bạn không phải kiểm tra nó.)
Phiên bản nhân đôi và đảo ngược của chương trình
EDCBAEDCBA
nên mất thời gian bình phương về mặt N. Đó là, thời gian cần thiết để chấm dứt nên tỷ lệ thuận với N * N. Vì vậy, nếu N = 1 chấm dứt trong khoảng một giây, N = 60 sẽ mất khoảng một giờ để chấm dứt.
Chi tiết
Bạn cần thể hiện hoặc lập luận rằng các chương trình của bạn đang chạy trong sự phức tạp mà bạn nói chúng là. Đưa ra một số dữ liệu thời gian là một ý tưởng tốt nhưng cũng cố gắng giải thích tại sao về mặt lý thuyết sự phức tạp là chính xác.
Thật tốt nếu trong thực tế thời gian các chương trình của bạn không đại diện hoàn hảo cho sự phức tạp của chúng (hoặc thậm chí là xác định). ví dụ: đầu vào N + 1 đôi khi có thể chạy nhanh hơn N.
Môi trường bạn đang chạy chương trình của bạn có vấn đề. Bạn có thể đưa ra các giả định cơ bản về cách các ngôn ngữ phổ biến không bao giờ cố tình lãng phí thời gian trong các thuật toán, nhưng, ví dụ, nếu bạn biết phiên bản cụ thể của Java thực hiện sắp xếp bong bóng thay vì thuật toán sắp xếp nhanh hơn , thì bạn nên tính đến điều đó nếu bạn thực hiện bất kỳ sắp xếp nào .
Đối với tất cả các phức tạp ở đây giả sử chúng ta đang nói về các tình huống xấu nhất , không phải trường hợp tốt nhất hoặc trường hợp trung bình.
Độ phức tạp không gian của các chương trình không quan trọng, chỉ có độ phức tạp thời gian.
Các chương trình có thể xuất ra bất cứ điều gì. Nó chỉ là vấn đề mà họ lấy số nguyên dương N và có độ phức tạp thời gian chính xác.
Bình luận và các chương trình multiline được cho phép. (Bạn có thể cho rằng
\r\n
đảo ngược là\r\n
để tương thích với Windows.)
Nhắc nhở Big O
Từ nhanh nhất đến chậm nhất O(1), O(N), O(N^2), O(2^N)
(thứ tự 1, 2, 4, 3 ở trên).
Điều khoản chậm hơn luôn chiếm ưu thế, ví dụ O(2^N + N^2 + N) = O(2^N)
.
O(k*f(N)) = O(f(N))
cho hằng số k. Vì vậy O(2) = O(30) = O(1)
và O(2*N) = O(0.1*N) = O(N)
.
Ghi nhớ O(N^2) != O(N^3)
và O(2^N) != O(3^N)
.
Chấm điểm
Đây là mã golf bình thường. Chương trình gốc ngắn nhất (thời gian không đổi một) tính bằng byte thắng.
n = input(); for i in xrange(n): pass
có độ phức tạp theo cấp số nhân, bởi vì nó thực 2 ** k
hiện các bước, k = log_2(n)
kích thước đầu vào ở đâu. Bạn nên làm rõ liệu đây là trường hợp, vì nó thay đổi đáng kể các yêu cầu.