Một thuật toán nhanh hơn có nghĩa là gì trong khoa học máy tính lý thuyết?


18

Nếu có một thuật toán chạy trong thời gian cho một số vấn đề A và ai đó nghĩ ra một thuật toán chạy đúng lúc, , trong đó , nó có được coi là một cải tiến so với thuật toán trước không?O(f(n))O(f(n)/g(n))g(n)=o(f(n))

Liệu nó có ý nghĩa, trong bối cảnh của khoa học máy tính lý thuyết, để đưa ra một thuật toán như vậy?


4
Theo "thuật toán nhanh hơn", chúng tôi có nghĩa là "thuật toán nhanh hơn bất thường".
Yuval Filmus

@YuvalFilmus ý bạn là gì với "tiệm cận"
không xác định

1
Chạy trong thời gian o(f(n)) .
Yuval Filmus

Câu trả lời:


26

Không, một thuật toán chạy trong thời gian , trong đó , không nhất thiết được coi là một cải tiến. Ví dụ: giả sử và . Khi đó là thời gian bị ràng buộc tồi tệ hơn .O(f(n)/g(n))g(n)=o(f(n))f(n)=ng(n)=1/nO(f(n)/g(n))=O(n2)O(f(n))=O(n)

Để cải thiện thuật toán chạy trong thời gian , bạn cần đưa ra thuật toán chạy trong thời gian , nghĩa là, trong thời gian cho một số hàm .o ( f ( n ) ) g ( n ) g ( n ) = o ( f ( n ) )f(n)o(f(n))g(n)g(n)=o(f(n))

Nếu tất cả những gì bạn biết là một thuật toán chạy trong thời gian , thì không rõ liệu thuật toán chạy trong thời gian có phải là một sự cải tiến hay không, bất kể là. Điều này là do O lớn chỉ là giới hạn trên của thời gian chạy. Thay vào đó, người ta thường xem xét độ phức tạp của trường hợp xấu nhất và ước tính nó là một lớn thay vì chỉ là một lớn .O ( g ( n ) ) f ( n ) , g ( n ) Θ OO(f(n))O(g(n))f(n),g(n)ΘO


21
Có thể tốt hơn khi lấy trong đoạn đầu tiên của bạn. Sử dụng một chức năng giảm cảm thấy một chút gian lận-y. g(n)= =1
David Richerby

1
@DavidR Richby: Có thể một chút, nhưng OP không bao giờ nói rằng họ có thuật toán chạy trong nên không thể giả sử tính đơn điệu. Ôi(g(n))
Kevin

7
@Kevin Chắc chắn nhưng bối cảnh là khoa học máy tính và, trong khoa học máy tính, ký hiệu big-O thường được sử dụng cho các chức năng không tăng. Có lẽ người hỏi đã suy nghĩ trong những điều khoản đó.
David Richerby

11

Hãy nhớ rằng Ký hiệu là có nghĩa là để phân tích như thế nào nhiệm vụ phát triển cho các kích cỡ khác nhau của đầu vào, và đặc biệt là lá ra các yếu tố chất nhân, hạ bậc hạn, và hằng số.O(...)

Giả sử bạn có thuật toán với thời gian chạy thực tế là 1 n 2 + 2 n + 1 (giả sử bạn thực sự có thể đếm các hướng dẫn và biết thời gian chính xác, v.v., được thừa nhận là một giả định rất lớn trong các hệ thống hiện đại). Sau đó, giả sử bạn đưa ra một thuật toán mới xảy ra là O ( n ) , nhưng thời gian chạy thực tế là 1000 n + 5000 . Ngoài ra, giả sử bạn biết phần mềm sử dụng thuật toán này sẽ không bao giờ thấy kích thước sự cố là n > 10 .Ôi(n2)1n2+2n+1Ôi(n)1000n+5000n>10

Vì vậy, bạn sẽ chọn cái nào - thuật toán sẽ mất 15000 đơn vị thời gian, hay thuật toán O ( n 2 ) sẽ chỉ mất 121 đơn vị? Bây giờ nếu phần mềm của bạn phát triển để xử lý các kích thước sự cố n > 100000 , bạn sẽ chọn cái nào? Bạn sẽ làm gì nếu kích thước vấn đề của bạn thay đổi lớn?Ôi(n)Ôi(n2)n>100000


2
"Không bao giờ thấy kích thước sự cố của n> 10" - sau đó chúng tôi sẽ không sử dụng ký hiệu O nào cả, chúng tôi sẽ ...
AnoE

5
@AnoE Số đơn giản để tranh luận. Logic tương tự áp dụng cho dù bạn đang phân tích cho một kích thước vấn đề 10 so với 1e5 hay phân tích cho 1e6 so với 1e9.
twalberg

1
@AnoE Hầu hết các chương trình máy tính không cố gắng xử lý kích thước sự cố tăng vô hạn. Vì vậy, sẽ có một sự đánh đổi. Đó là lý do tại sao big-O dành cho khoa học máy tính lý thuyết và các khái niệm có thể được áp dụng để cải thiện các chương trình thực tế.
mbomb007

Chính xác, @ mbomb007. Tiêu đề câu hỏi là "Thuật toán nhanh hơn có nghĩa là gì trong khoa học máy tính lý thuyết ?" và anh ta có cái này trong cơ thể: "Liệu nó có ý nghĩa, trong bối cảnh khoa học máy tính lý thuyết ...".
AnoE

@AnoE Từ kinh nghiệm, ký hiệu O được sử dụng khi n <10 mọi lúc! Không phải đó là một ý tưởng hay ... nhưng đó hoàn toàn là một việc đã được thực hiện!
Cort Ammon - Hồi phục lại

5

Nói chung, điều đó có nghĩa là, đối với bất kỳ kích thước đầu vào nào đủ lớn, thời gian chạy trường hợp xấu nhất của thuật toán cũ chậm hơn so với đầu vào mới. Đó là tương đương với hình thức , nơi g là sự phức tạp của thuật toán mới và f mức độ phức tạp thời gian của cái cũ.g(n)o(f(n))gf

Đôi khi, mặc dù, các nhà khoa học máy tính quan tâm đến hiệu suất trường hợp trung bình. Các ví dụ điển hình là Sắp xếp nhanh: thời gian chạy trường hợp xấu nhất của nó là trong khi chúng ta đều biết những người khác chạy trong Θ ( n log n ) thời gian, nhưng nó sử dụng rộng rãi trong thực tế vì trung bình hợp cụ thể thời gian chạy tốt của nó. Nó cũng có thể được điều chỉnh để chạy rất nhanh trong các trường hợp thường xuyên nhất trong tự nhiên, chẳng hạn như các mảng chủ yếu theo đúng thứ tự.Θ(n2)Θ(nđăng nhậpn)

Và đôi khi, ngay cả các nhà khoa học máy tính lý thuyết cũng sử dụng tốc độ nhanh hơn giống như người bình thường. Ví dụ, hầu hết các triển khai của các lớp Chuỗi đều có Tối ưu hóa Chuỗi ngắn (còn được gọi là Tối ưu hóa Chuỗi nhỏ), mặc dù nó chỉ tăng tốc mọi thứ cho các chuỗi ngắn và là chi phí thuần túy cho các chuỗi dài hơn. Khi kích thước đầu vào ngày càng lớn hơn, thời gian chạy của hoạt động Chuỗi với SSO sẽ cao hơn bởi một thuật ngữ không đổi nhỏ, do đó, theo định nghĩa tôi đã đưa ra trong đoạn đầu tiên, loại bỏ SSO khỏi lớp Chuỗi giúp nó nhanh hơn .”trên thực tế, tuy nhiên, hầu hết các chuỗi nhỏ, vì vậy SSO làm cho hầu hết các chương trình mà sử dụng chúng nhanh hơn, và hầu hết các giáo sư khoa học máy tính biết tốt hơn để đi xung quanh đòi hỏi mà mọi người chỉ nói về đơn đặt hàng của tiệm cận độ phức tạp thời gian.


1

Không có một định nghĩa thống nhất nào về "thuật toán nhanh hơn" là gì. Không có một cơ quan quản lý nào quyết định liệu một thuật toán có nhanh hơn thuật toán khác hay không.

Để chỉ ra lý do tại sao, tôi muốn đưa ra hai kịch bản khác nhau thể hiện khái niệm mờ ám này.

Ví dụ đầu tiên là một thuật toán tìm kiếm một danh sách liên kết các dữ liệu không được sắp xếp. Nếu tôi có thể thực hiện thao tác tương tự với một mảng, tôi không có thay đổi nào về số đo hiệu suất Oh lớn. Cả hai tìm kiếm là O (n). Nếu tôi chỉ nhìn vào các giá trị Oh lớn, tôi có thể nói rằng tôi đã không cải thiện gì cả. Tuy nhiên, người ta biết rằng việc tra cứu mảng nhanh hơn so với việc đi theo danh sách được liên kết trong phần lớn các trường hợp, do đó người ta có thể quyết định rằng điều đó làm cho thuật toán "nhanh hơn", mặc dù Oh lớn không thay đổi.

Nếu tôi có thể sử dụng ví dụ truyền thống về lập trình robot để làm bánh sandwich PBJ, tôi có thể chỉ ra ý tôi là cách khác. Hãy xem xét điểm mà người ta đang mở lọ bơ đậu phộng.

Pick up the jar
Grab the lid
Unscrew the lid

Đấu với

Pick up the jar
Put the jar back down
Pick up the jar
Put the jar back down
Pick up the jar
Put the jar back down
Pick up the jar
Put the jar back down
Pick up the jar
Put the jar back down
Pick up the jar
Grab the lid
Unscrew the lid

Ngay cả trong môi trường lý thuyết hàn lâm nhất mà tôi có thể nghĩ ra, bạn sẽ thấy rằng mọi người chấp nhận rằng thuật toán đầu tiên nhanh hơn thuật toán thứ hai, mặc dù kết quả ký hiệu Oh lớn là như nhau.

Ngược lại, chúng ta có thể xem xét một thuật toán để phá vỡ mã hóa RSA. Hiện tại, người ta nhận thấy rằng quá trình này có thể là O (2 ^ n), trong đó n là số bit. Hãy xem xét một thuật toán mới chạy nhanh hơn n ^ 100 Điều này có nghĩa là quy trình mới của tôi chạy trong O (2 ^ n / n ^ 100). Tuy nhiên, trong thế giới của mật mã học, việc tăng tốc đa thức cho một thuật toán theo cấp số nhân theo truyền thống không được coi là một tốc độ lý thuyết tăng tốc cả. Khi làm bằng chứng bảo mật, người ta cho rằng kẻ tấn công có thể phát hiện ra một trong những cách tăng tốc này và nó sẽ không có hiệu lực.

Vì vậy, trong một trường hợp, chúng ta có thể thay đổi O (n) thành O (n) và gọi nó nhanh hơn. Trong một trường hợp khác, chúng ta có thể thay đổi O (2 ^ n) thành O (2 ^ n / n ^ 100) và khẳng định không có sự tăng tốc có ý nghĩa nào cả. Đây là lý do tại sao tôi nói không có một định nghĩa thống nhất cho một "thuật toán nhanh hơn". Nó luôn luôn phụ thuộc vào ngữ cảnh.


1

Tôi chưa thể bình luận, nhưng tôi cảm thấy như các câu trả lời hiện tại, trong khi chính xác và nhiều thông tin, không giải quyết một phần của câu hỏi này. Đầu tiên, chúng ta hãy viết một biểu thức tương đương với .Một(n)Ôi(f(n))

 0cf<| lim supnMột(n)f(n)= =cf

Bây giờ, chúng ta hãy giả sử chúng ta đang nói về một gia tăng tùy tiện chức năng nơi lim sup n g ( n ) = và chúng ta hãy tạo chức năng h ( n ) = f ( n )g(n)lim supng(n)= = .h(n)= =f(n)g(n)

Chúng tôi đang cho rằng thời gian chạy của "cải thiện" thuật toán O ( h ( n ) ) . Giả sử thời gian chạy của thuật toán gốc A ( n ) cũng ở O ( h ( n ) ) . Điều này có thể được viết như sau.Một'(n)Ôi(h(n))Một(n)Ôi(h(n))

 0ch<| lim supnMột(n)h(n)= =ch

Sử dụng quy tắc giới hạn, chúng ta cũng có thể viết:

ch= =lim supnMột(n)h(n)= =lim supnMột(n)g(n)f(n)= =cflim supng(n)

ch<cf= =0

Câu lệnh contrapositive là: Nếu , thì A ( n ) O ( h ( n ) ) .cf0Một(n)Ôi(h(n))

Nói cách, là một "cải tiến" trên Một ( n ) theo các điều kiện bổ sung mà A ( n ) q ( f ( n ) )g ( n ) được tùy tiện tăng.Một'(n)Một(n)Một(n)Θ(f(n))g(n)

Thêm vào đó, điều này sẽ cho thấy tại sao các tuyên bố rằng không đủ mạnh để rút ra kết luận về việc liệu Một ' ( n ) là một "sự cải tiến." Nói tóm lại, A ( n ) có thể đã ở O ( h ( n ) ) .Một(n)Ôi(f(n))Một'(n)Một(n)Ôi(h(n))


1
Giới hạn của bạn nên được giới hạn vượt trội.
Yuval Filmus

1
@YuvalFilmus Cập nhật
Jared Goguen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.