Tôi đã cố gắng để cải thiện trên Andy 's answer, nhưng ông khá nhiều đóng đinh nó. Giải pháp đầu tiên là tạo hình chóp suối - mỗi cuộc gọi tới fib
tạo ra một luồng mã vạch khác và mỗi luồng mới này sẽ tự tạo luồng mới, v.v.
Để được rõ ràng, có ba suối kết quả từ một cuộc gọi đến fib
:
- Một tạo ra bởi
fib
trong fib zip fib.tail
- Một tạo ra bởi
fib.tail
trong fib zip fib.tail
- Một tạo ra bởi
map
(hãy nhớ, map
tạo bộ sưu tập mới)
Vì hai người đầu tiên gọi tới fib
, họ sẽ tạo ba luồng mỗi lần, v.v.
Dưới đây là một "hình ảnh" thô của nó:
1
1
1 2 1
1 3 1 2 1
1 2 1 5 1 3 1 2 1
1 3 1 2 1 8 1 2 1 5 1 3 1 2 1
Và điều này đi và về. Luồng giữa được tính bằng cách sử dụng các luồng cao nhất bên trái và bên phải (fib và fib.tail). Mỗi người trong số họ được tính bằng cách sử dụng các luồng thấp hơn trên của họ bên trái và bên phải. Mỗi luồng dưới được tính bằng các luồng được hiển thị trên dòng cuối cùng.
Chúng tôi có thể tiếp tục điều này, nhưng bạn có thể thấy rằng, vào thời điểm chúng tôi tính toán 8, chúng tôi đã có 14 dòng mã nguồn khác đang diễn ra.
Nếu bạn thay đổi nó def
-val
, tất cả những con suối mới biến mất, bởi vì fib
và fib.tail
sẽ đề cập đến một dòng hiện thay vì tạo dòng mới. Và do không có luồng mới nào được tạo nên sẽ không có thêm cuộc gọi nào tới fib
và fib.tail
.
Bây giờ, nếu bạn nhìn vào câu trả lời thứ hai, bạn sẽ nhận thấy rằng có một cuộc gọi fib
duy nhất và không map
hoặc phương pháp tương tự, vì vậy không có hiệu ứng nhân.
Nguồn
2012-01-04 13:21:38
Ví dụ không phải là đệ quy đuôi. –
@ DanielC.Sobral Bạn có thể giải thích lý do tại sao việc thực hiện 2 tính toán mỗi số Fibonacci trong 'O (1)' nhưng số 1 thực hiện nó trong 'O (N)' – Michael
Rất tiếc ... Tôi đã nói về lần đầu tiên .. Hãy để tôi xóa bình luận của tôi ... –