Biện minh cho việc bỏ qua các yếu tố liên tục trong Big O


20

Nhiều lần nếu các phức tạp có các hằng số như 3n, chúng ta bỏ qua hằng số này và nói O (n) chứ không phải O (3n). Tôi không thể hiểu làm thế nào chúng ta có thể bỏ qua thay đổi ba lần như vậy? Một số thứ đang thay đổi nhanh hơn 3 lần so với những thứ khác! Tại sao chúng ta bỏ bê thực tế này?


Các ngữ nghĩa của "có thể" là quan trọng. Trong thực tế, chúng ta thường không thể bỏ qua những thay đổi như vậy, nhưng điều đó (tức là mô tả hiệu suất thuật toán trong thế giới thực) không phải là những gì ký hiệu Landau được tạo ra. Formalisms chính xác hơn làm tồn tại.
Raphael

Câu trả lời:


22

Để hợp lý hóa làm thế nào các ký hiệu tiệm cận bỏ qua các yếu tố không đổi, tôi thường nghĩ về nó như thế này: độ phức tạp tiệm cận không phải để so sánh hiệu suất của các thuật toán khác nhau, đó là để hiểu cách hiệu suất của các thuật toán riêng lẻ so với kích thước đầu vào.

Chẳng hạn, chúng ta nói rằng một hàm có bước là O ( n ) , bởi vì, nói một cách đại khái, đối với các đầu vào đủ lớn, nhân đôi kích thước đầu vào sẽ không nhiều hơn gấp đôi số bước đã thực hiện. Tương tự, O ( n 2 ) có nghĩa là nhân đôi kích thước đầu vào sẽ tăng gấp bốn lần số bước và O ( log n ) có nghĩa là nhân đôi kích thước đầu vào sẽ tăng số lượng bước lên nhiều nhất là một số hằng số.3nO(n)O(n2)O(logn)

Đó là một công cụ để nói thuật toán nào mở rộng quy mô tốt hơn, không phải thuật toán nào hoàn toàn nhanh hơn.


11

Đầu tiên, như các câu trả lời khác đã giải thích, hoặc để đặt nó trong các từ, một hàm là O ( 3 n ) khi và chỉ khi nó là O ( n ) . f = O ( 3 n ) có nghĩa là rằng có tồn tại một điểm N và một yếu tố C 3 sao cho với mọi n N , f ( n ) C 33O(3n)=O(n)O(3n)O(n)f=O(3n)NC3nN . Bây giờ chọn C 1 = 3 C 3 : cho tất cả n N , f ( n ) C 1n , do đó f = O ( n ) . Bằng chứng của converse là tương tự.f(n)C33nC1=3C3nNf(n)C1nf=O(n)

Bây giờ đến lý do tại sao đây là công cụ phù hợp. Quan sát rằng khi chúng tôi đo lường độ phức tạp của thuật toán, chúng tôi không đưa ra một đơn vị. Chúng tôi không đếm giây hoặc hướng dẫn máy: chúng tôi đếm một số bước cơ bản không xác định mà mỗi bước mất một thời gian. Chúng tôi làm điều đó bởi vì thực hiện cùng một thuật toán trên một máy khác sẽ thay đổi thời gian cần thiết cho mỗi lệnh - nhân tần số xung nhịp với và thời gian thực hiện đi từ f ( n ) đến f ( n ) / 33f(n)f(n)/3. Nếu chúng tôi thực hiện cùng một thuật toán trong một ngôn ngữ khác hoặc trên một hệ thống khác, thời gian của mỗi bước cơ bản có thể khác nhau, nhưng một lần nữa, đó là quá nhiều chi tiết: chúng tôi hầu như không quan tâm đến những khác biệt đó.

Khi bạn quan tâm đến thời gian chính xác, độ phức tạp tiệm cận không liên quan: độ phức tạp tiệm cận cho bạn biết điều gì xảy ra với kích thước đầu vào rất lớn, có thể hoặc không phải là kích thước đầu vào thực tế mà bạn đang xử lý.


Cũng lưu ý rằng Sedgewick trong mình "Giới thiệu về Phân tích các thuật toán" những người ủng hộ sử dụng o(g)như là biện pháp đúng, ví dụ, có là cách mô tả thời gian chạy (vẫn xét về các hoạt động cơ bản chi phối nếu bạn muốn, nhưng bao gồm cả yếu tố không đổi làm phiền OP). limng(n)T(n)=1
vonbrand

2
@vonbrand Có phải Sedgewick thực sự nói vậy không? Định nghĩa thông thường của lim n ( T ( n ) / g ( n ) ) = 0 (tức là, phần cách khác xung quanh và giới hạn là không, không đoàn kết).T(n)o(g(n)limn(T(n)/g(n))=0
David Richerby

3

Nhắc lại định nghĩa của Big-O:

khi và chỉ khi tồn tại c > 0 sao cho f ( n ) c g ( n ) cho tất cả n .f(n)O(g(n))c>0f(n)cg(n)n

Theo định nghĩa này, chúng ta có cho mọi hằng số d . Mục đích của ký hiệu O là chính xác để đơn giản hóa các biểu thức theo cách này. Thật vậy, 3 n tăng nhanh gấp 3 lần n , nhưng cả hai đều tuyến tính. Điều này có hợp lý hay không - điều đó phụ thuộc vào bối cảnh. Nhưng nếu bạn đồng ý sử dụng ký hiệu O , thì theo định nghĩa này sẽ giữ.dnO(n)dO3nnO


2
Điều này cung cấp một lời giải thích tuyệt vời về Big-O, nhưng không có lời giải thích nào về lý do TẠI SAO chúng ta sử dụng định nghĩa này.
jmite

Như tôi đã viết - mục đích là để đơn giản hóa cuộc sống của chúng ta. Có thể là do chúng tôi không biết chi phí chính xác của một hoạt động nguyên tử hoặc bởi vì chúng tôi quan tâm đến ký hiệu tiệm cận. Tôi không tìm thấy TẠI SAO một câu hỏi toán học thú vị, mà là một câu hỏi triết học. Chúng tôi có thể, về mặt kỹ thuật, làm mà không có nó. Nó sẽ chỉ làm cho mọi thứ thực sự xấu xí và khó làm việc.
Shaull

3

Ký hiệu Big O là một đơn vị trung bình miễn phí để đo lường sự thay đổi hiệu suất, do đó không phụ thuộc vào chi phí tương đối của các nguyên thủy tính toán.

Tóm lại: Ký hiệu Big O là loại đơn vị đo lường tương đối, không có đơn vị (trái ngược với phép đo tuyệt đối). Nó chỉ có thể đo lường sự thay đổi hiệu suất, không phải hiệu suất tuyệt đối, mà hằng số là vấn đề rất nhiều. Ưu điểm là điều này làm cho nó thực hiện phần lớn độc lập, bằng cách cho phép phân tích đơn giản hơn có thể bỏ qua chi phí tương đối của các hoạt động cơ bản, miễn là các chi phí này có giới hạn trên và dưới cố định dương. Nhưng hậu quả là các yếu tố không đổi là vô nghĩa . Tuy nhiên, ngay cả đối với mục đích dự định của nó, phân tích độ phức tạp tiệm cận có thể được đặt câu hỏi trên các căn cứ khác , và phải được xem xét cẩn thận. Ví dụ, kích thước đầu vào thô có thể không phải là tham số phù hợp để xem xét.

Một nhận xét đầu tiên là câu hỏi của bạn không được nêu chính xác. Khi bạn bỏ qua hằng số trong 3 n , thực sự có "thay đổi ba lần", nhưng cả hai đều thay đổi theo cùng một tỷ lệ và bạn không thể khẳng định rằng "[một] thứ thay đổi nhanh gấp 3 lần so với thứ khác".33n

Một lý do tốt để bỏ qua sự liên tục trong ký hiệu Landau là chúng tôi không có đơn vị nào chúng tôi có thể dựa vào. Khi ai đó nói rằng A sống xa bạn gấp đôi so với B, điều này có ý nghĩa độc lập với bất kỳ đơn vị nào. Chúng tôi có thể đồng ý về điều đó mặc dù bạn đo khoảng cách bằng inch trong khi tôi làm điều đó trong những năm ánh sáng. Nhưng đo khoảng cách tuyệt đối đòi hỏi phải xác định đơn vị và công thức số của nó phụ thuộc vào đơn vị được chọn.

Thời gian thực tế được thực hiện bởi một thuật toán phụ thuộc vào thời gian thực hiện các hoạt động cơ bản, phụ thuộc rất nhiều vào máy. Bạn có thể đếm số lượng các hoạt động cơ bản, nhưng không có lý do gì để tin rằng tất cả chúng đều mất cùng một thời gian và luôn có thể gộp nhiều hoạt động thành một hoạt động, hoặc ngược lại, phân tách một hoạt động thành các hoạt động nhỏ hơn, sao cho số đó các hoạt động không thực sự có ý nghĩa, trừ khi bạn đồng ý trên một máy ảo tham chiếu. Được tham chiếu độc lập là một lợi thế.

Một quan điểm khác về lợi thế của phương pháp này là tất cả những gì bạn quan tâm trong phân tích là đếm số lượng các hoạt động cơ bản, miễn là chi phí của chúng có giới hạn trên và giới hạn dưới dương. Bạn không phải lo lắng về chi phí cá nhân.

Tuy nhiên, cái giá phải trả cho lợi thế đó là đánh giá chi phí tính toán được đưa ra với đơn vị không xác định và ví dụ, thời gian tính toán có thể là nano giây hoặc milimet - chúng tôi thậm chí không thử biết. Nói cách khác, các yếu tố không đổi là vô nghĩa, vì các đơn vị thay đổi không thể tách rời với việc thay đổi hệ số không đổi và không có đơn vị tham chiếu nào được sử dụng.

Như Patrick87 đã lưu ý , điều này đủ để hiểu cách thuật toán chia tỷ lệ theo kích thước đầu vào, nhưng nó sẽ không đưa ra một thước đo tuyệt đối về hiệu suất, thiếu dựa vào một đơn vị tham chiếu. Việc hủy một máy trừu tượng tham chiếu chung có thể được thực hiện khi người ta thực sự muốn so sánh hiệu suất của các thuật toán riêng biệt, nhưng khó hơn để đảm bảo rằng so sánh không bị sai lệch bởi các chi tiết thực hiện. Trong độ phức tạp tiệm cận, rủi ro này được tránh vì bạn so sánh thuật toán với chính nó.

Dù sao, chỉ có một lập trình viên ngây thơ sẽ chỉ dựa vào độ phức tạp tiệm cận để chọn một thuật toán. Có nhiều tiêu chí khác, bao gồm hằng số chưa được tiết lộ và chi phí thực tế của các hoạt động cơ bản. Hơn nữa, độ phức tạp của trường hợp xấu nhất có thể là một chỉ báo kém, bởi vì nguồn gốc của độ phức tạp trong trường hợp xấu nhất có thể hiếm khi xảy ra, và trên các mảnh của đầu vào đủ nhỏ để nó không bị giới hạn. Ví dụ, các trình phân tích cú pháp chung cho Ngữ pháp liền kề cây có độ phức tạp về lý thuyết và khá hữu dụng trong thực tế. Trường hợp xấu nhất mà tôi biết là kiểu suy luận đa hình Damas-Hindley-MilnerO(n6)thuật toán được sử dụng cho ML, có độ phức tạp trường hợp xấu nhất theo cấp số nhân. Nhưng điều đó dường như không làm phiền người dùng ML, hoặc để ngăn việc viết các chương trình rất lớn trong ML. Có nhiều hơn các hằng số quan trọng. Trên thực tế, phân tích tiệm cận liên quan đến một thước đo chi phí tính toán với một số đo lường về độ phức tạp của đầu vào. Nhưng kích thước thô có thể không phải là biện pháp đúng.

Sự phức tạp giống như tính quyết định, nó có thể xấu về mặt lý thuyết, nhưng điều đó có thể không liên quan đến hầu hết không gian dữ liệu ... đôi khi. Phân tích độ phức tạp tiệm cận là một công cụ tốt và được thiết kế tốt, với những ưu điểm và hạn chế của nó, giống như tất cả các công cụ. Có hoặc không khám phá hằng số, có thể là vô nghĩa, sử dụng phán đoán là cần thiết.


2

Các câu trả lời khác cung cấp giải thích tuyệt vời về lý do tại sao, theo định nghĩa của Big-O, .O(n)=O(3n)

Về lý do tại sao chúng tôi thực sự làm điều này trong CS, vì vậy chúng tôi có một mô tả nhỏ gọn về hiệu quả của thuật toán. Ví dụ, có thể có một thuật toán có câu lệnh if, trong đó một nhánh thực hiện lệnh và nhánh kia thực hiện 3 n lệnh. Điều này có nghĩa là số lượng chính xác thay đổi cho từng đầu vào, ngay cả đối với các đầu vào có cùng độ dài. Chúng ta có thể tìm thấy một số cho mỗi đầu vào, nhưng sử dụng ký hiệu big-O cho chúng ta một thước đo độ phức tạp thời gian giữ cho TẤT CẢ các đầu vào.n3n

Điều này hữu ích hơn nhiều trong việc đoán thuật toán sẽ nhanh như thế nào. Mặt khác, chúng ta phải xem xét một chức năng từng phần lớn, điều này sẽ rất khó hiểu.

Lý do chính khác là để các phép đo này độc lập với phần cứng. Các trình biên dịch và kiến ​​trúc khác nhau sẽ thay đổi cùng một mã thành các bộ hướng dẫn rất khác nhau. Tuy nhiên, nếu chúng ta biết rằng số lượng hướng dẫn là tuyến tính, hàm mũ, v.v., thì chúng ta có ý tưởng về tốc độ thuật toán giữ, bất kể máy tính thực tế mà chúng ta biên dịch hoặc chạy trên đó.


1

f(n)=O(g(n))lim supnf(n)g(n)<+

g(n)=ng(n)=3n

O(n2)=O(.00005321n2+1000000000n+1046803)f=


2
=O(...)

fO(g)fO(nn2)f(x)=h(x)xx=n=
yo '

f(n)f

Tôi cũng thường làm như vậy, vì biết rằng đó cũng là một sự lạm dụng ký hiệu;)
yo '

-1

Hãy để tôi giải thích cho bạn đơn giản. Hãy để chúng tôi lấy n = 100000. Bây giờ, 3n là gì? Nó là 300000 ( Vâng, nó là 3 lần của n ) Nhưng n ^ 2 là gì? 10000000000 . ( đó là 1 lakh nếp gấp của n ) .. So sánh n ^ 2 với n. 3 là không đáng kể khi chúng ta so sánh với 1 lakh. vì vậy, chúng ta có thể loại bỏ nó

Hãy suy nghĩ nếu n là một tỷ hoặc hàng nghìn tỷ đồng. Trong trường hợp này, một lần nữa chúng ta sẽ so sánh 3 với hàng tỷ hoặc hàng nghìn tỷ đồng. Bây giờ, bạn biết tại sao chúng ta có thể bỏ qua 3.


2
Ba năm vẫn là một thời gian dài hơn một năm.
Yuval Filmus

Tôi không thấy cách này trả lời câu hỏi theo bất kỳ cách hữu ích nào. Nó chắc chắn không thêm bất cứ điều gì qua các câu trả lời lâu năm, hiện có.
Raphael
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.