Trực giác thuật toán cho độ phức tạp logarit


60

Tôi tin rằng tôi có một nắm bắt hợp lý về các phức tạp như , và .O(1)Θ(n)Θ(n2)

Xét về danh sách, là một tra cứu liên tục, do đó, nó chỉ là người đứng đầu danh sách. là nơi tôi sẽ đi bộ toàn bộ danh sách và đang đi bộ danh sách một lần cho mỗi thành phần trong danh sách.O(1)Θ(n)Θ(n2)

Có cách nào trực quan tương tự để nắm bắt ngoài việc chỉ biết nó nằm ở đâu đó giữa và không?Θ(logn)O(1)Θ(n)


8
log n là để "tìm kiếm": nghĩ rằng tìm kiếm nhị phân
Suresh

2
Sử dụng để đặt câu hỏi này là không chính xác, vì nó chỉ biểu thị một giới hạn trên. Ví dụ, thời gian không đổi là . sẽ thích hợp hơn. Xem câu hỏi meta: meta.cs.stackexchange.com/questions/182/ KẻOO(logn)θ
Aryabhata


Một lưu ý nhỏ: Trong cài đặt Turing Machine cổ điển, tất cả các thuật toán là , vì chúng cần đọc từng ký hiệu của đầu vào ít nhất một lần. Tìm kiếm nhị phân có thể được thực hiện trong vì chúng tôi có lời hứa rằng danh sách được sắp xếp, chẳng hạn. Ω(n)O(logn)
chazisop

1
Một đóng góp muộn: theo định nghĩa, logarit cơ sở của một số chỉ là số lần bạn nhân với chính nó để có được . . Ví dụ: . Vì vậy, nếu bạn có một số và bạn muốn tìm hiểuchỉ cần chia nó cho cho đến khi bạn đạt đến (giả sử là lũy thừa của vì đơn giản). Số lượng các phân chia bằng . Các thuật toán thể hiện hành vi phân chia này có thời gian chạy trongbnbnbl=nl=logb(n)n l o g b ( n ) = ? b 1 n b l o g b ( n ) O ( l o g ( n ) )23=8log2(8)=3nlogb(n)=?b1nblogb(n)O(log(n)).
saadtaame

Câu trả lời:


54

Độ phức tạp thường được kết nối với phân ngành. Khi sử dụng danh sách làm ví dụ, hãy tưởng tượng một danh sách có các thành phần được sắp xếp. Bạn có thể tìm kiếm trong danh sách này trong thời gian - bạn thực sự không cần phải xem xét từng yếu tố vì tính chất được sắp xếp của danh sách.O ( log n )Θ(logn)O(logn)

Nếu bạn nhìn vào phần tử ở giữa danh sách và so sánh nó với phần tử bạn tìm kiếm, bạn có thể ngay lập tức nói liệu nó nằm ở nửa bên trái hay bên phải của mảng. Sau đó, bạn có thể chỉ cần thực hiện một nửa này và lặp lại quy trình cho đến khi bạn tìm thấy nó hoặc đạt được một danh sách với 1 mục mà bạn so sánh một cách tầm thường.

Bạn có thể thấy rằng danh sách giảm một nửa hiệu quả mỗi bước. Điều đó có nghĩa là nếu bạn nhận được một danh sách có độ dài , các bước tối đa bạn cần để đạt được danh sách một mục là . Nếu bạn có danh sách mục, bạn chỉ cần bước, đối với danh sách bạn chỉ cần bước, v.v.5 128 = 2 7 7 1024 = 2 10 10325128=2771024=21010

Như bạn có thể thấy, số mũ trong luôn hiển thị số bước cần thiết. Logarit được sử dụng để "trích xuất" chính xác số mũ này, ví dụ . Nó cũng khái quát để liệt kê độ dài không phải là sức mạnh của hai chiều dài.n2nlog2210=10


4
Cần lưu ý rằng điều này chỉ O(log n)khi danh sách có quyền truy cập ngẫu nhiên thời gian không đổi. Trên nhiều triển khai danh sách tiêu biểu (danh sách liên kết) đây làO(n log n)
asm

1
Tìm kiếm nhị phân không hoạt động trên danh sách cho việc thiếu con trỏ; nó thường được thực hiện trên mảng.
Raphael

Tìm kiếm nhị phân chỉ hoạt động tốt trên danh sách. Nó chỉ là khá vô nghĩa vì tài khoản phức tạp hơn nhiều so với yêu cầu / hữu ích / thực tế.
Anton

@AndrewMyer Tìm kiếm danh sách được liên kết chính xác hơnO(n)
phant0m

1
@ phant0m Vâng, tôi đã mất một chút để nhận ra rằng nó giả sử bạn đang di chuyển từ vị trí hiện tại thay vì di chuyển từ đầu mỗi lần.
asm

38

Về mặt cây (cân bằng) (giả sử, cây nhị phân, vì vậy tất cả 's là cơ sở 2):log

  • Θ(1) đang lấy gốc của cây
  • Θ(logn) là một bước đi từ gốc đến lá
  • Θ(n) đang duyệt qua tất cả các nút của cây
  • Θ(n2) là hành động trên tất cả các tập hợp con hai nút trong cây, ví dụ: số lượng đường dẫn khác nhau giữa hai nút bất kỳ.
  • Θ(nk) - khái quát hóa ở trên cho bất kỳ tập hợp con của các nút (cho một hằng số )kk
  • k = 1 , 2 , ... , nΘ(2n) là các hành động trên tất cả các tập hợp con có thể có của các nút (tập hợp con của tất cả các kích thước có thể, nghĩa là, .). Ví dụ, số lượng cây con khác nhau của cây.k=1,2,,n

5
Để thêm vào đó, trực giác cho xuất phát từ hai điều: 1.) Các tái T ( n ) = T ( Θ(loglogn)và 2.) Tìm kiếm nhị phân trên một cái gì đó có kích thướclog(n)tức là tìm kiếm nhị phân trên chiều cao của cây. T(n)=T((n))+1log(n)
mcorley

17

Để có thể thực hiện được, bạn cần có thể cắt giảm kích thước bài toán theo tỷ lệ theo một số lượng tùy ý đối với n với hoạt động thời gian không đổi.O(logn)n

Ví dụ: trong trường hợp tìm kiếm nhị phân, bạn có thể giảm một nửa kích thước bài toán với mỗi thao tác so sánh.

Bây giờ, bạn có phải giảm một nửa kích thước vấn đề, thực tế là không. Một thuật toán là ngay cả khi nó có thể cắt giảm không gian tìm kiếm vấn đề 0,0001%, miễn là tỷ lệ phần trăm và thao tác sử dụng để cắt giảm kích thước sự cố không đổi, đó là thuật toán O ( log n ) , nó sẽ không phải là một thuật toán nhanh, nhưng nó vẫn là O ( log n ) với hằng số rất lớn. (Giả sử chúng ta đang nói về log n với nhật ký cơ sở 2)O(logn)O(logn)O(logn)logn


1
Sẽ thế nào nếu 'số tiền cắt giảm' không đổi?
Svish

@Svish Nếu bạn có thể cắt giảm vấn đề ở mức tích cực, nó vẫn sẽ là thuật toán , mặc dù có lẽ nó sẽ không còn bị ràng buộc chặt chẽ nữa. Tỷ lệ tiêu cực là khó nói. Giả định được đưa ra để làm cho câu trả lời khá đơn giản trong trường hợp này, vì câu hỏi này có giá trị riêng của nó, bạn rất sẵn lòng hỏi đây là một câu hỏi. O(logn)
Ken Li

Vâng, tôi có nghĩa là không gian tìm kiếm vấn đề luôn luôn giảm, nhưng không nhất thiết phải ở một tốc độ không đổi. Chỉ nghĩ về "miễn là tỷ lệ phần trăm và thao tác mà nó sử dụng để cắt giảm kích thước sự cố không đổi, đó là thuật toán O (log n)"; nếu nó có một tên khác nếu tỷ lệ phần trăm không đổi.
Svish

8

Hãy nghĩ về thuật toán để chuyển đổi số thập phân thành nhị phânn

while n != 0:
   print n%2, 
   n = n/2

whileVòng lặp này chạy lần.log(n)


1
Chắc chắn chương trình này lặp lần, nhưng nói chung là khi chúng ta nói về O ( f ( s ) ) phức tạp, s là kích thước của đầu vào của bạn. Ở đây kích thước của đầu vào của bạn đã là s = log n , vì vậy tôi sẽ nói chương trình này chỉ là tuyến tính (tính theo O ( s ) )lognO(f(s))ss=lognO(s)
jmad

@jmad Đúng rồi. Nhưng ví dụ này không cung cấp cho bạn trực giác vào log (n).
Pratik Deoghare

@jmad Tôi cũng có thể sử dụng thuật toán để tạo số ngẫu nhiên nhưng tôi muốn nó đơn giản nhất có thể.
Pratik Deoghare

8

Có, nằm trong khoảng từ 1 đến n , nhưng nó gần với 1 hơn n . Là gì log ( n ) ? Hàm log là hàm nghịch đảo của lũy thừa. Hãy để tôi bắt đầu với số mũ và bạn sẽ hiểu rõ hơn về logarit là gì.log(n)1n1nlog(n)

Hãy xem xét hai số, 2 100 . 2 1002 nhân với chính nó 100 lần. Bạn có thể với một số nỗ lực đếm 100 số, nhưng bạn có thể đếm 2 100 không? Tôi cá là bạn không thể. Tại sao? 2 100 là một con số lớn đến mức nó lớn hơn số lượng của tất cả các nguyên tử trong vũ trụ. Suy ngẫm về điều đó một lát. Đó là một con số khổng lồ đến nỗi nó cho phép bạn đặt cho mỗi nguyên tử một tên (số). Và số lượng nguyên tử trong móng tay của bạn có lẽ là hàng tỷ. 2 100 nên là đủ cho bất cứ ai (ý định chơi chữ :)).100210021002100100210021002100

Bây giờ, giữa hai số, 2 100 , 100 là logarit của 2 100 (trong cơ sở 2 ). 100 tương đối là một con số nhỏ hơn 2 100 . Bất cứ ai cũng nên có 100 vật dụng khác nhau trong nhà của họ. Nhưng, 2 100 là đủ tốt cho vũ trụ. Nghĩ về nhà vs vũ trụ khi nghĩ về log ( n )n .10021001002100210021001002100log(n)n

Trường hợp lũy thừa và logarit đến từ đâu? Tại sao họ rất quan tâm đến khoa học máy tính? Bạn có thể không nhận thấy, nhưng lũy ​​thừa là ở khắp mọi nơi. Bạn đã trả lãi cho thẻ tín dụng? Bạn vừa trả một vũ trụ cho ngôi nhà của bạn (Không quá tệ, nhưng đường cong phù hợp). Tôi muốn nghĩ rằng lũy ​​thừa xuất phát từ quy tắc sản phẩm, nhưng những người khác được chào đón để đưa ra nhiều ví dụ. Quy tắc sản phẩm là gì, bạn có thể yêu cầu; Và tôi sẽ trả lời.

Giả sử bạn có hai thành phố B , và có hai cách để đi giữa chúng. Số lượng đường dẫn giữa chúng là gì? Hai. Đó là chuyện nhỏ. Bây giờ hãy nói, có một thành phố C khác , và bạn có thể đi từ B đến C theo ba cách. Hiện tại có bao nhiêu con đường giữa AC ? Sáu, phải không? Làm thế nào bạn có được điều đó? Bạn đã đếm chúng? Hay bạn đã nhân chúng? Dù bằng cách nào, thật dễ dàng để thấy rằng cả hai cách đều cho kết quả tương tự nhau. Bây giờ nếu bạn thêm một thành phố D có thể đạt được từ C theo bốn cách, có bao nhiêu cách giữa ADABCBCACDCAD? Đếm nếu bạn không tin tưởng tôi, nhưng nó là bằng 24 . Bây giờ, nếu có mười thành phố và có hai con đường từ thành phố này sang thành phố khác, và chúng được sắp xếp giống như chúng nằm trên một đường thẳng. Có bao nhiêu con đường từ đầu đến cuối? Nhân chúng nếu bạn không tin tưởng tôi, nhưng tôi sẽ nói với bạn là có 2 10 , là 1024 . Thấy rằng 2 10 là mũ kết quả của 1010 là logarit của 2 10 . 10 là một con số nhỏ so với 1024 .2342421010242101010210101024

Các hàm logarit nn2 n (lưu ý rằng 2 là của logarit cơ sở). Nếu bạn nhân log b ( n ) với b lần (lưu ý rằng b là cơ sở của logarit), bạn sẽ nhận được n . log ( n ) rất nhỏ, quá nhỏ so với n , đó là kích thước của ngôi nhà của bạn trong đó n là kích thước của vũ trụ.log2(n)nn2n2logb(n)bbnlog(n)nn

Trên một lưu ý thực tế, các thực hiện rất giống với các hàm hằng. Chúng phát triển với n , nhưng chúng phát triển rất chậm. Nếu bạn đã tối ưu hóa một chương trình để chạy trong thời gian logarit mà mất một ngày trước đó, bạn có thể sẽ chạy nó theo thứ tự vài phút. Kiểm tra chính mình với các vấn đề trên Project Euler.log(n)n


3
Mặc dù được viết độc đáo, câu trả lời này hầu như không chứa bất kỳ thông tin nào ngoài " thực sự nhỏ". log(n)
Raphael

3
Tôi đã cố gắng đưa ra một trực giác cho việc nó nhỏ như thế nào.
Ravi

5

Để tiếp tục chủ đề của bạn, giống như liên tục đoán vị trí x nằm trong danh sách và được thông báo "cao hơn" hoặc "thấp hơn" (về chỉ số).O(logn)x

Nó vẫn dựa trên kích thước của danh sách, nhưng bạn chỉ cần truy cập một phần nhỏ của các yếu tố.


4

Nếu chúng ta có một thuật toán chia để trị , và chúng tôi chỉ cần lập một cuộc gọi đệ quy cho một bài toán con, và nó là trường hợp thứ hai trong định lý tổng thể , tức là mức độ phức tạp thời gian của phần không đệ quy là , sau đó các độ phức tạp của thuật toán sẽ là Θ ( lg k + 1 n ) .Θ(lgkn)Θ(lgk+1n)

Nói cách khác, khi chúng ta có một thuật toán chia và chinh phục với một lệnh gọi đệ quy cho chính nó về một vấn đề có kích thước là một yếu tố không đổi của vấn đề hiện tại và thời gian trong phần không đệ quy là (không đổi), sau đó thời gian chạy của thuật toán sẽ là lg n .Θ(1)lgn

Các tìm kiếm nhị phân thuật toán là ví dụ cổ điển.


1

Trực giác là số lần bạn có thể giảm một nửa số, giả sử n, trước khi nó giảm xuống 1 là O (lg n).

Để hình dung, hãy thử vẽ nó dưới dạng cây nhị phân và đếm số cấp bằng cách giải tiến trình hình học này.

2^0+2^1+...+2^h = n

Chào mừng đến với trang web! Tất nhiên những gì bạn nói là đúng nhưng tôi không thấy những gì nó thêm vào câu trả lời hiện có. Một số câu trả lời đã nói rằng logarit là số lần bạn có thể chia cho hai lần trước khi nhấn 1 và câu trả lời của Ran đã nói rằng là chiều cao của cây nhị phân có n lá. lognn
David Richerby
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.