Độ phức tạp thời gian của chức năng này là gì?


7

Đây là một ví dụ trong bài giảng của tôi. Hàm này có độ phức tạp thời gian không? Bởi vì trường hợp xấu nhất là chức năng đi vào nhánh và 2 vòng lặp lồng nhau với độ phức tạp thời gian là và , vì vậy nó là . Tôi có đúng khôngÔi(nđăng nhậpn)elseđăng nhậpnnÔi(nđăng nhậpn)

int j = 3;
int k = j * n / 345;
if(k > 100){
    System.out.println("k: " + k);
}else{
    for(int i=1; i<n; i*=2){
        for(int j=0; j<i; j++){
            k++;
        }
    }
}

Câu trả lời:


5

Độ phức tạp thời gian của thuật toán được đề cập là Ôi(1), vì K>100 bạn có một hoạt động liên tục (println), và bạn biết: j=3,k=3n/345100=3n/345n=11500, nghĩa cho n11500 thuật toán của bạn có thời gian chạy liên tục (phần khác là không đổi, vì chỉ dành cho n<11500 sẽ được gọi).

Để rõ ràng hơn hãy xem câu hỏi này .


có lẽ chỉ để hoàn thành câu trả lời của bạn, bạn nên đề cập rằng khi nói về sự phức tạp của thời gian, chúng ta chỉ quan tâm đến những gì xảy ra khi n. Hoặc bạn có thể liên kết đến một trong những câu hỏi liên quan đến sự phức tạp, như câu hỏi này
Ran G.

@RanG. Bạn hoàn toàn đúng, Thật ra tôi đã nghĩ viết một định nghĩa chính thức về Big-Oh, nhưng tôi nghĩ mọi người đều biết điều này, thực sự là bạn đã đủ để tìm thấyn0 cho giá trị ban đầu, c0cho hệ số không đổi. Tôi xác địnhn0, nhưng tôi đã không đề cập c0(có vẻ như đã rõ), nhưng vâng, tôi sẽ liên kết nó với câu trả lời của Raphael (trong tất cả những gì tôi lười viết).

4

EDIT: Như Saeed Amiri đã chỉ ra, đây thực sự là Ôi(1), vì lớn không có triệu chứng n, elsechi nhánh không thực sự được thực hiện; các ifphần được thực thi, đó là trivially thời gian liên tục. Phần còn lại của câu trả lời này, mà tôi để lại để tham khảo, sẽ đúng nếu, ví dụ, điều kiện là k < 100. Xin lỗi cho sự pha trộn lên.

Độ phức tạp thời gian về cơ bản sẽ theo thứ tự số lần kđược tăng lên trong forvòng lặp lồng nhau . Có một số thứ thêm đang diễn ra, nhưng nếu bạn nghĩ về nó, đó chỉ là chơi với các yếu tố không đổi. Bao nhiêu lần sẽk được tăng lên?

Khi nào Tôi= =1, kđược tăng lên một lần. Khi nàoTôi= =2, kđược tăng thêm hai lần. Khi nàoTôi= =x, k được tăng lên xlần bổ sung. Bây giờ chúng ta hãy giả định rằngn= =2m+1. Sau đó, lần lặp cuối cùng của vòng lặp bên trong sẽ khiến ktăng lên2m lần

k được tăng tổng cộng 1+2+...+2m lần, hoặc 2(m+1)-1lần Nhớ lại rằng `n= =2m+1. Vì thến-1= =2mvà chúng ta có điều đó k được tăng lên 2(n-1)-1 tổng số lần.

k được tăng lên một số lần tuyến tính trong n; ergo, đây là tất cảÔi(n).


-1 Độ phức tạp thời gian độc lập với vòng lặp for. (Xem câu trả lời của tôi, và tự mình thử nó).

1
@SaeedAmiri Rất tiếc, bạn đã đúng. Tôi sắp xếp elsemột phần mà không kiểm tra các điều kiện tiên quyết. Chỉnh sửa câu trả lời để phản ánh điều này.
Patrick87

Vâng, bây giờ câu trả lời của bạn là chính xác.

1

Mặc dù các ý kiến ​​về các nhánh if / other đều đúng, tôi sẽ nói câu trả lời là O (log n). Lý do là

System.out.println("k: " + k);

liên quan đến việc chuyển đổi một số nguyên thành đầu ra chuỗi và đây sẽ là O (log n) trong trường hợp chung (chỉ để in ra từng chữ số, ngay cả khi sử dụng bảng tra cứu).

Không chắc đó có phải là một phần mẹo của câu hỏi hay không ...


0

Hãy xem nào:

int j = 3; mất thời gian không đổi O (1).

int k = j * n / 345mất một số hàm thời gian logarit của các biến jn

if (k > 100) mất thời gian không đổi O (1).

System.out.println("k: " + k);mất chức năng thời gian logarit của k

for (int i=1; i<n; i*=2)lấy hàm thời gian logarit của n , (log (n)) là chính xác, bởi vì nếu t là số lần lặp của vòng lặp này thì giá trị của i có thể được biểu thị là: i = 2 t-1 , nếu t = 1 trong lần lặp đầu tiên, do đó vòng lặp tiếp tục miễn là 2 t - 1 <n , trong đó n không thay đổi.

Trong phép tính, nếu 2 t - 1 <n thì t - 1 <log 2 (n)

Và nếu t-1 <log 2 (n) thì t <log 2 (n) +1

Và nếu trong mỗi lần lặp, t được tăng thêm 1, chúng ta có thể thấy rằng vòng lặp này thực sự mất thời gian Θ (log (n)), nếu độ phức tạp thời gian chạy của mã bên trong vòng lặp này là không đổi, tức là O (1) tất nhiên!

Bên trong vòng lặp này, có một vòng lặp khác:

for (int j=0; j<i; j++) k++;

Hãy phân tích điều này:

k++; mất thời gian không đổi, tức là thời gian O (1).

Vì vậy, thật thú vị khi phân tích độ phức tạp thời gian chạy của vòng lặp for bên trong.

Hãy xem nào:

Theo mã của vòng lặp for bên trong này, có vẻ như có i lặp trong vòng lặp for bên trong này, vì vậy thời gian chạy của nó là Θ (i) , không chỉ O (i) , vì nó không bị ngắt ở giữa, nhưng hãy nhớ rằng i <n , vì vòng lặp for bên ngoài, nên mặc dù lúc đầu, nó chỉ cần 1 lần lặp khi i = 1 , 2 lần lặp khi i = 2 , 4 lần lặp khi i = 4 , 8 lần lặp khi i = 8 . .. và v.v., vì tôi nhân đôi chính nó ở cuối vòng lặp for bên ngoài trong dòng i * = 2 , nên trong tổng số thực hiện là 1 + 2 + 4 + 8 + ... lặp đi lặp lại nhưng cho đến khi invì vậy số lần lặp tối đa có thể có trong vòng lặp for bên trong này là khi i = n-1 trong trường hợp xấu nhất, vì vậy nếu trong lần thực hiện cuối cùng của vòng lặp for bên trong, nó đã chạy các lần lặp n-1 , vì vậy trước khi nó chạy ( n-1) / 2 lần lặp và trước đó nó đã chạy (n-1) / 4 lần lặp và trước đó nó đã chạy (n-1) / 8 lần lặp ... vì vậy trong tổng số lần thực hiện là:

n-1 + (n-1) / 2 + (n-1) / 4 + (n-1) / 8 ... = (n-1) (1 + 1/2 + 1/4 + 1/8 ...) = (n-1) (2) = 2n-2 = Θ (n)

Hãy nhớ lại rằng 1 + 1/2 + 1/4 + 1/8 ... = 2 là tổng của chuỗi hình học nổi tiếng.

Hãy nhớ rằng vòng lặp for bên ngoài mất (log (n))

Và vòng lặp for bên trong mất Θ (n).

Và độ phức tạp thời gian chạy của vòng lặp for bên trong vòng lặp for là độ phức tạp thời gian chạy của vòng lặp for bên ngoài nhân với độ phức tạp thời gian chạy của vòng lặp for bên trong, do đó cần có thời gian chạy Θ (nlogn).

Vì vậy, tóm lại, thời gian chạy của chức năng này là Θ (nlogn) .

Hy vọng rằng điều này trả lời tốt câu hỏi của bạn và dạy cho bạn cách phân tích độ phức tạp thời gian chạy của các thuật toán và hàm.


Tại sao câu trả lời của tôi nhanh chóng được bình chọn?
Trao đổi ngăn xếp chia tay

Phân tích của tôi là sai?
Trao đổi ngăn xếp chia tay

"int k = j * n / 345 có một số hàm thời gian logarit của các biến j và n". Bạn đang sử dụng chi phí thời gian logarit cho mỗi thao tác trên các số, nhưng thường thì chi phí thời gian không đổi cho mỗi thao tác được sử dụng, như dự định của câu hỏi. Ngoài ra, phân tích của bạn về 2 vòng lặp là sai, vì j chỉ chạy cho đến khi tôi ở vòng lặp bên trong. O (n), như được đề cập bởi người khác, là chính xác.
Albert Hendriks

Được rồi, tôi đồng ý với bạn.
Trao đổi ngăn xếp chia tay
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.