Ký hiệu Big Oh không đề cập đến giá trị không đổi


12

Tôi là một lập trình viên và mới bắt đầu đọc Thuật toán. Tôi không hoàn toàn bị thuyết phục với các ký hiệu cụ thể là Bog Oh, Big Omega và Big Theta. Lý do là theo định nghĩa của Big Oh, nó nói rằng nên có một hàm g (x) sao cho nó luôn lớn hơn hoặc bằng f (x). Hoặc f (x) <= cn cho tất cả các giá trị của n> n0.

Tại sao chúng ta không đề cập đến giá trị không đổi trong định nghĩa? Ví dụ: giả sử hàm 6n + 4, chúng ta ký hiệu là O (n). Nhưng điều đó không đúng khi định nghĩa này phù hợp với mọi giá trị không đổi. Điều này chỉ giữ tốt khi c> = 10 và n> = 1. Đối với các giá trị nhỏ hơn của c hơn 6, giá trị của n0 tăng. Vậy tại sao chúng ta không đề cập đến giá trị không đổi như là một phần của định nghĩa?


4
Làm thế nào để bạn đề xuất để đại diện cho giá trị không đổi, chính xác?
Daniel B

1
Đưa điểm của bạn lên một bước nữa, bất kỳ hàm kết thúc nào là O (1) nếu bạn ràng buộc n.
Brian

Câu trả lời:


22

O (n) và ký hiệu thứ tự khác là (thường) không liên quan đến hành vi của các hàm đối với các giá trị nhỏ. Nó liên quan đến hành vi của các hàm đối với các giá trị rất lớn, cụ thể là các giới hạn khi n di chuyển về phía vô cực.

Các hằng số về mặt kỹ thuật nhưng chúng thường được trừu tượng hóa khi một khi n trở nên đủ lớn, giá trị của c hoàn toàn không liên quan. Nếu giá trị của c là quan trọng, chúng ta có thể đưa nó vào phân tích nhưng trừ khi các hàm được so sánh có các yếu tố hằng số rất lớn hoặc nếu hiệu quả là mối quan tâm đặc biệt quan trọng, thì chúng thường không.


3
Ví dụ: xây dựng các kim tự tháp là O (n), sắp xếp các hình ảnh của chúng là O (n log n) - tại một số điểm bạn có thể có đủ các kim tự tháp mà sẽ mất nhiều thời gian hơn để sắp xếp các hình ảnh hơn là xây dựng một hình ảnh mới! Nhưng chỉ cho một số lượng lớn kim tự tháp!
Martin Beckett

Câu trả lời tốt, nhưng đối với một N nhất định và hai thuật toán thường rơi vào cùng một "họ" phức tạp, có thể có công trong việc thực hiện chính xác những gì OP gợi ý và bao gồm ít nhất là các hệ số tương đối. Một thuật toán tuyến tính với số lượng lệnh gấp đôi cho mỗi phần tử vì một thuật toán khác có thể được gọi là * O * (2N) cho alg thứ hai * O * (N) để hiển thị sự khác biệt tương đối, bởi vì với bất kỳ N nào, thuật toán đầu tiên sẽ luôn luôn gấp đôi thời gian thực hiện lần thứ hai; tuy nhiên, khi so sánh với một chức năng của một họ phức tạp khác, chẳng hạn như * O * (NlogN), các hệ số không thành vấn đề.
KeithS

22

Có một số lý do, nhưng có lẽ lý do quan trọng nhất là các hằng số là một chức năng của việc thực hiện thuật toán, chứ không phải chính thuật toán. Thứ tự của một thuật toán là hữu ích để so sánh các thuật toán bất kể việc thực hiện chúng.

Thời gian chạy thực tế của quicksort thường sẽ thay đổi nếu nó được triển khai trong C hoặc Python hoặc Scala hoặc Postcript. Điều tương tự cũng áp dụng cho sắp xếp bong bóng - thời gian chạy sẽ thay đổi lớn dựa trên việc thực hiện.

Tuy nhiên, điều sẽ không thay đổi là thực tế là, tất cả những thứ khác đều bằng nhau, vì tập dữ liệu sẽ lớn hơn thời gian cần thiết để chạy một loại bong bóng sẽ tăng nhanh hơn thời gian cần thiết để chạy quicksort trong trường hợp điển hình, bất kể ngôn ngữ hay máy nào họ đang thực hiện với, giả sử một cách thực hiện hợp lý. Thực tế đơn giản này cho phép bạn đưa ra những suy luận thông minh về chính các thuật toán khi các chi tiết cụ thể không có sẵn.

Thứ tự của một thuật toán lọc ra các yếu tố, trong khi quan trọng trong các phép đo trong thế giới thực, có xu hướng chỉ là nhiễu khi so sánh các thuật toán trong bản tóm tắt.


9

Ký hiệu Big O theo định nghĩa cho biết: Ký hiệu Big O được xây dựng dựa trên trực giác rằng với tất cả các giá trị n ở bên phải của n ', giá trị của f (n) nằm trên hoặc dưới cg (n). Các hằng số cũng không quan trọng khi bạn đi đến các yếu tố có giá trị cao (biến) (như n-vuông hoặc n-cube) vì chúng chỉ là các hằng số và không phải là các đại lượng khác nhau có thể trở nên lớn như các yếu tố đó. Đưa ra dưới đây là biểu đồ của ký hiệu Big-O.
For a given function g(n), we denote by O(g(n)) the set of functions:
O(g(n)) = {f(n): there exist positive constants c and n' such that 0<=f(n)<=c.g(n) for all n > n'}




nhập mô tả hình ảnh ở đây

Bản chất của ký hiệu này là trong thực tế " how lower is f(n) from c.g(n) and not when it starts becoming lower".


Trong trường hợp đó, với mọi O (n) cũng là Big theta của n vì theo định nghĩa cho một hằng số, nó sẽ là một giới hạn dưới và đối với một số hằng số đó là một giới hạn trên. ví dụ 6n + 4 cũng là một theta (n) lớn vì khi c nhỏ hơn 10 thì nó luôn luôn là giới hạn dưới. và khi c lớn hơn 10 thì nó là giới hạn trên. Vì vậy, chúng ta có thể nói rằng đối với bất kỳ ký hiệu Big Oh nào cũng là một theta lớn?
Pradeep

1
Bạn đang nói theo cách khác: "Big Theta có nghĩa là Big Oh". Và Big -Oh có thể được thay thế bằng Big-Theta cho các giới hạn chặt chẽ không có triệu chứng.
Vaibhav Agarwal

9

Trong phân tích thuật toán, Thứ tự tăng trưởng là sự trừu tượng hóa chính và nó đưa ra tốc độ thay đổi thời gian chạy khi kích thước đầu vào thay đổi. Giả sử một thuật toán có thời gian chạy f(n) = 2n + 3. Bây giờ chúng tôi cắm một số kích thước đầu vào,

n = 10: 2 * 10 + 3 = 23

n = 100: 2 * 100 + 3 = 203

n = 10000: 2 * 10000 + 3 = 20003

n = 1000000: 2 * 1000000 + 3 = 2000003

n = 100000000 : 2 * 100000000 + 3 = 200000003

Có thể thấy, thứ tự tăng trưởng chủ yếu được xác định bởi biến số n; hằng số 2 và 3 ít quan trọng hơn và khi kích thước đầu vào tăng lên, chúng càng trở nên ít quan trọng hơn trong việc xác định nó. Đây là lý do tại sao các hằng số phân tích thuật toán được trợ cấp cho biến xác định thứ tự tăng trưởng của hàm.


1

(vì đây là câu trả lời dài hơn, hãy đọc phần in đậm để tóm tắt )

Hãy lấy ví dụ của bạn và từng bước thực hiện nó, hiểu mục đích đằng sau những gì chúng ta đang làm. Chúng tôi bắt đầu với chức năng của bạn và mục tiêu tìm kiếm ký hiệu Big Oh của nó:

f(n) = 6n+4

Đầu tiên, hãy O(g(n))là ký hiệu Big Oh mà chúng tôi đang cố gắng tìm kiếm f(n). Từ định nghĩa của Big Oh, chúng ta cần tìm một đơn giản hóa g(n) nơi tồn tại một số hằng số cn0nơi nào c*g(n) >= f(n)đúng với tất cả nlớn hơn n0.

Đầu tiên, chúng ta hãy chọn g(n) = 6n + 4(sẽ mang lại O(6n+4)Big Oh). Trong trường hợp này, chúng tôi thấy rằng c = 1và bất kỳ giá trị nào n0sẽ đáp ứng các yêu cầu toán học từ định nghĩa của chúng tôi về Big Oh, vì g(n)luôn luôn bằng f(n):

c*g(n)      >=  f(n)    
1*(6n + 4)  >=  6n + 4    //True for all n's, so we don't need to pick an n0

Tại thời điểm này, chúng tôi đã đáp ứng các yêu cầu toán học. Nếu chúng ta dừng lạiO(6n+4) , rõ ràng điều này không hữu ích hơn viết f(n), vì vậy nó sẽ bỏ lỡ mục đích thực sự của ký hiệu Big Oh: để hiểu độ phức tạp thời gian chung của thuật toán! Vì vậy, hãy chuyển sang bước tiếp theo: đơn giản hóa.

Đầu tiên, chúng ta có thể đơn giản hóa ra khỏi 6nBig Oh O(4)không? Không! (Tập thể dục cho người đọc nếu họ không hiểu tại sao)

Thứ hai, chúng ta có thể đơn giản hóa 4để Big Oh được O(6n)không? Đúng! Trong trường hợp đó g(n) = 6n, vì vậy:

c*g(n)    >=  f(n)
c*6n      >=  6n + 4     

Tại thời điểm này, hãy chọn c = 2từ đó bên trái sẽ tăng nhanh hơn (12) so với bên phải (6) cho mỗi lần tăng n.

2*6n      >=  6n + 4

Bây giờ chúng ta cần tìm một số dương n0trong đó phương trình trên đúng với tất cả các ngiá trị lớn hơn giá trị đó. Vì chúng ta đã biết rằng bên trái đang tăng nhanh hơn bên phải, tất cả những gì chúng ta phải làm là tìm một giải pháp tích cực. Do đó, vì n0 = 2làm cho những điều trên trở thành sự thật, chúng tôi biết rằng g(n)=6n, hoặc O(6n)là một ký hiệu Big Oh tiềm năng cho f(n).

Bây giờ, chúng ta có thể đơn giản hóa 6để Big Oh được O(n)không? Đúng! Trong trường hợp đó g(n) = n, vì vậy:

c*g(n)      >=  f(n)    
c*n         >=  6n + 4    

Hãy chọn c = 7vì bên trái sẽ tăng nhanh hơn bên phải.

7*n         >=  6n + 4

Chúng tôi thấy rằng những điều trên sẽ đúng với tất cả nlớn hơn hoặc bằng n0 = 4. Vì vậy, O(n)là một ký hiệu Big Oh tiềm năng cho f(n). Chúng ta có thể đơn giản hóa g(n)nữa không? Không!

Cuối cùng, chúng tôi đã thấy rằng ký hiệu Big Oh đơn giản nhất f(n)O(n). Tại sao chúng ta trải qua tất cả điều này? Bởi vì bây giờ chúng ta biết đó f(n)là tuyến tính , vì ký hiệu Big Oh là phức tạp tuyến tính O(n). Điều tuyệt vời là bây giờ chúng ta có thể so sánh độ phức tạp thời gian của f(n)các thuật toán khác! Ví dụ, bây giờ chúng ta biết rằng f(n)là có thể so sánh thời gian phức tạp đến các chức năng h(n) = 123n + 72, i(n) = n, j(n) = .0002n + 1234, vv; bởi vì sử dụng cùng một quy trình đơn giản hóa được nêu ở trên, tất cả chúng đều có độ phức tạp thời gian tuyến tính của O(n).

Ngọt!!!


Xin chào, giải thích tốt. Tôi vẫn còn ít nghi ngờ. 1. Chúng ta không thể biến 6n + 4 thành O (4) vì có giá trị biến 'n'. Đây có phải là câu trả lời? 2. trong khi đơn giản hóa, bạn đã chọn c = 7 và tính tương ứng n0 đến 4. Điều gì được thực hiện để quyết định c = 7 và không nhỏ hơn 7? bởi vì dựa trên giá trị của c, n0 sẽ thay đổi.
Pradeep

@Pradeep: Cho 1, bạn đúng. Để giải thích sâu hơn: Nếu chúng ta cố gắng O(4), điều đó sẽ làm cho phương trình bất đẳng thức của chúng ta c*4 >= 6n+4và đối với bất kỳ cchúng ta đã chọn, chúng ta luôn có thể tìm thấy một giá trị trong đó tất cả các giá trị nở trên sẽ làm cho bất đẳng thức sai.
Briguy37

@Pradeep: Đối với 2, các giá trị thực tế cn0không quan trọng. Điều quan trọng là n0tồn tại cho cchúng ta chọn. Để điều này là đúng, bên trái của bất đẳng thức phải tăng nhanh hơn bên phải cho các giá trị lớn của n. c=6không tốt cho việc này ( 6n >= 6n+4không bao giờ đúng), vì vậy tôi đã chọn c=7. Tôi có thể dễ dàng chọn c=10, c=734hoặc c=6.0000001vẫn có thể thấy rằng có một số n0tồn tại để làm cho bất đẳng thức đúng n >= n0, điều đó có nghĩa là Big Oh chúng tôi đang kiểm tra là hợp lệ.
Briguy37

Cảm ơn đã giải thích rõ ràng. Đây là những gì tôi đã tìm kiếm chính xác. Một lần nữa xin cảm ơn.
Pradeep

@Pradeep: Vui mừng tôi có thể giúp :)
Briguy37

1

Nếu bạn có chức năng thực hiện 6n + 4, câu hỏi liên quan là "6 cái gì?". Như một bình luận hỏi: hằng số của bạn đại diện cho cái gì? Trong thuật ngữ vật lý, các đơn vị của yếu tố không đổi của bạn là gì?

Lý do tại sao ký hiệu O () được sử dụng rộng rãi để mô tả hiệu suất thuật toán là vì không có cách di động để trả lời câu hỏi đó. Các bộ xử lý khác nhau sẽ mất một số chu kỳ đồng hồ khác nhau và lượng thời gian khác nhau để thực hiện cùng một tính toán cơ bản, hoặc chúng có thể gộp các tính toán cơ bản có liên quan khác nhau. Các ngôn ngữ máy tính khác nhau, hoặc các mô tả chính thức và không chính thức khác nhau như mã giả, sẽ biểu diễn các thuật toán theo những cách khó so sánh trực tiếp. Ngay cả các triển khai trong cùng một ngôn ngữ cũng có thể biểu diễn cùng một thuật toán theo các cách khác nhau - các chi tiết định dạng tầm thường như số lượng dòng sang một bên, nhìn chung bạn sẽ có nhiều lựa chọn cấu trúc tùy ý để thực hiện bất kỳ thuật toán nào.

Nhìn vào một cách khác: chúng tôi sử dụng "thuật toán" không phải để mô tả một triển khai cụ thể, mà để mô tả toàn bộ một lớp các triển khai tiềm năng của cùng một quy trình chung. Sự trừu tượng hóa này bỏ qua các chi tiết triển khai có lợi cho việc ghi lại một cái gì đó có giá trị chung và yếu tố hiệu suất không đổi là một trong những chi tiết này.

Điều đó nói rằng, các mô tả thuật toán thường đi kèm với văn hóa dân gian, ghi chú hoặc thậm chí điểm chuẩn thực tế mô tả hiệu suất của việc triển khai thực tế trên phần cứng thực tế. Điều này cung cấp cho bạn một ý tưởng sơ bộ về loại yếu tố không đổi mong đợi, nhưng nó cũng nên được thực hiện bằng một hạt muối vì hiệu suất thực tế phụ thuộc vào những thứ như tối ưu hóa bao nhiêu công việc đã thực hiện. Ngoài ra, về lâu dài, hiệu suất tương đối của các thuật toán có thể so sánh có xu hướng trôi đi khi kiến ​​trúc của các bộ xử lý mới nhất và lớn nhất thay đổi ...


0

Toàn bộ khái niệm ký hiệu Big-Oh đặc biệt bỏ qua các hằng số và trình bày phần quan trọng nhất của hàm mô tả thời gian chạy của thuật toán.

Hãy quên định nghĩa chính thức trong giây lát. Đó là chức năng tồi tệ hơn (tăng trưởng nhanh hơn), n^2 - 5000hay 5000 n + 60000? Đối với nít hơn khoảng 5000, hàm tuyến tính lớn hơn (và do đó kém hơn). Ngoài ra (giá trị chính xác 5013?), Phương trình bậc hai lớn hơn.

Vì có nhiều hơn (khá nhiều hơn) các số dương lớn hơn 5000 ít hơn, nên chúng ta coi phương trình bậc hai là hàm 'lớn hơn' (tệ hơn) nói chung. Ký hiệu đơn hàng (Big-Oh, v.v.) thực thi điều đó (bạn luôn có thể loại bỏ một phụ gia và hằng số nhân bằng cách sử dụng các định nghĩa đó).

Tất nhiên, mọi thứ không phải lúc nào cũng đơn giản. Đôi khi bạn làm muốn biết những hằng số. Cái nào tốt hơn Sắp xếp chèn hay Sắp xếp bong bóng? Cả hai đều như vậy O(n^2). Nhưng cái này thực sự tốt hơn cái kia. Với phân tích công phu hơn, người ta có thể nhận được các hằng số như bạn đang tự hỏi. Việc tính toán hàm Big-Oh thường dễ hơn nhiều so với hàm chính xác hơn.

Big-Oh bỏ qua các hằng số này để đơn giản hóa và làm cho các so sánh quan trọng nhất trở nên dễ dàng hơn. Chúng tôi thích ký hiệu này vì thông thường chúng tôi không muốn biết về các hằng số (hầu hết không liên quan).

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.