Chuỗi Fibonacci trong Python sử dụng đầu vào
Dãy Fibonacci là một dãy số nguyên khá nổi tiếng. Trình tự xuất hiện một cách tự nhiên trong nhiều vấn đề và có một định nghĩa đệ quy đẹp. Học cách tạo nó là một bước thiết yếu trong hành trình của lập trình viên thực dụng hướng tới việc làm chủ đệ quy. Trong hướng dẫn này, bạn sẽ tập trung tìm hiểu dãy Fibonacci là gì và cách tạo dãy bằng Python Show
Trong hướng dẫn này, bạn sẽ học cách
Để tận dụng tối đa hướng dẫn này, bạn nên biết kiến thức cơ bản về ký hiệu Big O, lập trình hướng đối tượng, các phương thức đặc biệt của Python, câu lệnh điều kiện, hàm và cấu trúc dữ liệu cơ bản như danh sách, hàng đợi và ngăn xếp. Làm quen với những khái niệm này sẽ giúp bạn hiểu rất nhiều về những khái niệm mới mà bạn sẽ khám phá trong hướng dẫn này Hãy đi sâu vào ngay Tải xuống miễn phí. Nhận một chương mẫu từ Python Basics. Giới thiệu thực tế về Python 3 để xem cách bạn có thể đi từ trình độ mới bắt đầu lên trình độ trung cấp trong Python với một chương trình giảng dạy hoàn chỉnh, cập nhật về Python 3. 8 Bắt đầu với dãy FibonacciLeonardo Fibonacci là một nhà toán học người Ý, người đã có thể nhanh chóng đưa ra câu trả lời cho câu hỏi này của Hoàng đế Frederick II của Swabia. “Một năm thu được bao nhiêu cặp thỏ, không kể số thỏ chết, giả sử mỗi cặp thỏ sinh thêm một cặp mỗi tháng và cặp vợ chồng trẻ nhất đã có thể sinh sản vào tháng thứ hai của cuộc đời?” Câu trả lời là trình tự sau đây Mẫu bắt đầu sau hai số đầu tiên, 0 và 1, trong đó mỗi số trong dãy luôn là tổng của hai số trước nó. Các nhà toán học Ấn Độ đã biết về dãy số này từ thế kỷ thứ sáu và Fibonacci đã tận dụng nó để tính toán sự tăng trưởng của quần thể thỏ F(n) được dùng để chỉ số cặp thỏ có mặt trong tháng thứ n, do đó, dãy có thể được biểu thị như sau Trong thuật ngữ toán học, bạn gọi đây là một quan hệ lặp lại, nghĩa là mỗi phần tử của chuỗi (ngoài 0 và 1) là một hàm của các phần tử trước đó Ngoài ra còn có một phiên bản của dãy số mà hai số đầu tiên đều là 1, như vậy Trong phiên bản thay thế này, F(0) vẫn hoàn toàn là 0, nhưng thay vào đó, bạn bắt đầu từ F(1) và F(2). Thuật toán vẫn giữ nguyên vì bạn luôn tính tổng hai số trước đó để lấy số tiếp theo trong dãy Với mục đích của hướng dẫn này, bạn sẽ sử dụng phiên bản của chuỗi bắt đầu bằng 0 Loại bỏ các quảng cáoKiểm tra đệ quy đằng sau dãy FibonacciTạo dãy Fibonacci là một bài toán đệ quy kinh điển. Đệ quy là khi một hàm tham chiếu đến chính nó để chia nhỏ vấn đề mà nó đang cố giải quyết. Trong mọi lệnh gọi hàm, vấn đề trở nên nhỏ hơn cho đến khi nó đạt đến trường hợp cơ sở, sau đó, nó sẽ trả về kết quả cho từng người gọi trung gian cho đến khi nó trả lại kết quả cuối cùng cho người gọi ban đầu Nếu bạn muốn tính số Fibonacci F(5), trước tiên, bạn cần tính các số trước của nó, F(4) và F(3). Và để tính F(4) và F(3), bạn cần tính các tiền thân của chúng. Việc phân tích F(5) thành các bài toán con nhỏ hơn sẽ như thế này Mỗi khi hàm Fibonacci được gọi, nó sẽ được chia thành hai bài toán con nhỏ hơn vì đó là cách bạn đã xác định quan hệ truy hồi. Khi nó đạt đến trường hợp cơ bản của F(0) hoặc F(1), cuối cùng nó có thể trả lại kết quả cho người gọi nó Để tính số thứ năm trong dãy Fibonacci, bạn giải các bài toán nhỏ hơn nhưng giống hệt nhau cho đến khi đạt đến các trường hợp cơ bản, nơi bạn có thể bắt đầu trả về kết quả Các bài toán con được tô màu trên biểu đồ này thể hiện các nghiệm lặp đi lặp lại cho cùng một bài toán. Nếu bạn đi sâu hơn vào cây, bạn sẽ tìm thấy nhiều giải pháp lặp đi lặp lại này. Điều này có nghĩa là để tạo ra một dãy Fibonacci theo cách đệ quy, bạn phải tính đi tính lại nhiều số trung gian. Đây là một trong những vấn đề cơ bản trong cách tiếp cận đệ quy đối với dãy Fibonacci Tạo đệ quy dãy Fibonacci trong PythonThuật toán tối thiểu và phổ biến nhất để tạo dãy Fibonacci yêu cầu bạn viết mã một hàm đệ quy tự gọi chính nó nhiều lần nếu cần cho đến khi tính được số Fibonacci mong muốn >>>
Bên trong 7, trước tiên bạn kiểm tra trường hợp cơ sở. Sau đó, bạn trả về tổng các giá trị có được từ việc gọi hàm với hai giá trị trước đó là 8. Việc hiểu danh sách ở cuối ví dụ tạo ra một dãy Fibonacci với mười lăm số đầu tiênChức năng này nhanh chóng rơi vào vấn đề lặp lại mà bạn đã thấy ở phần trên. Tính toán ngày càng đắt hơn khi 8 lớn hơn. Thời gian cần thiết tăng theo cấp số nhân vì hàm tính toán lặp đi lặp lại nhiều bài toán con giống hệt nhauGhi chú. Không thử chức năng này tại nhà với số lớn hơn 50. Tùy thuộc vào phần cứng của bạn, bạn có thể phải đợi một thời gian dài trước khi thấy kết quả—nếu bạn làm đến cùng Để tính F(5), 7 phải gọi chính nó mười lăm lần. Để tính F(n), độ sâu tối đa của cây lệnh gọi là n và vì mỗi lệnh gọi hàm tạo ra hai lệnh gọi hàm bổ sung, nên độ phức tạp về thời gian của hàm đệ quy này là O(2n)Hầu hết các cuộc gọi đó là dư thừa vì bạn đã tính toán kết quả của chúng. F(3) xuất hiện hai lần và F(2) xuất hiện ba lần. F(1) và F(0) là trường hợp cơ bản, vì vậy có thể gọi chúng nhiều lần. Bạn có thể muốn tránh sự lặp lại lãng phí này, đó là chủ đề của các phần sau Tối ưu hóa thuật toán đệ quy cho dãy FibonacciCó ít nhất hai kỹ thuật bạn có thể sử dụng để làm cho thuật toán tạo dãy Fibonacci hiệu quả hơn—nói cách khác, để làm cho việc tính toán mất ít thời gian hơn. Những kỹ thuật này đảm bảo rằng bạn không phải tính đi tính lại cùng một giá trị, đó là điều khiến thuật toán ban đầu trở nên kém hiệu quả. Chúng được gọi là ghi nhớ và lặp lại Ghi nhớ thuật toán đệ quyNhư bạn đã thấy trong đoạn mã trên, hàm Fibonacci tự gọi chính nó nhiều lần với cùng một đầu vào. Thay vì một cuộc gọi mới mỗi lần, bạn có thể lưu trữ kết quả của các cuộc gọi trước đó trong một thứ gì đó giống như bộ nhớ cache. Bạn có thể sử dụng danh sách Python để lưu trữ kết quả của các phép tính trước đó. Kỹ thuật này được gọi là ghi nhớ Ghi nhớ tăng tốc độ thực thi các hàm đệ quy đắt tiền bằng cách lưu trữ các kết quả đã tính toán trước đó vào bộ đệm. Bằng cách này, khi cùng một đầu vào xảy ra lần nữa, hàm chỉ cần tra cứu kết quả tương ứng và trả về kết quả đó mà không phải chạy lại tính toán. Bạn có thể tham khảo các kết quả này dưới dạng lưu trữ hoặc ghi nhớ Với tính năng ghi nhớ, bạn chỉ cần duyệt qua cây cuộc gọi có độ sâu n một lần sau khi trở về từ trường hợp cơ sở, khi bạn truy xuất tất cả các giá trị được tính toán trước đó được đánh dấu bằng màu vàng, F(2) và F(3), từ bộ đệm trước đó Đường màu cam cho biết không có đầu vào nào của hàm Fibonacci được gọi nhiều lần. Điều này làm giảm đáng kể độ phức tạp về thời gian của thuật toán từ hàm mũ O(2n) thành tuyến tính O(n) Ngay cả đối với các trường hợp cơ bản, bạn có thể thay thế việc gọi F(0) và F(1) bằng cách chỉ truy xuất các giá trị trực tiếp từ bộ đệm tại các chỉ số 0 và 1, vì vậy cuối cùng bạn chỉ gọi hàm sáu lần thay vì mười lăm lần Đây là bản dịch có thể có của việc tối ưu hóa này sang mã Python >>>
Trong ví dụ này, bạn sử dụng từ điển Python để lưu trữ các số Fibonacci đã tính. Ban đầu, 0 chứa các giá trị bắt đầu của dãy Fibonacci, 0 và 1. Bên trong hàm, trước tiên bạn kiểm tra xem số Fibonacci cho giá trị đầu vào hiện tại của 8 đã có trong 0 chưa. Nếu vậy thì bạn trả lại số trong tầm tayNếu không có số Fibonacci cho giá trị hiện tại của 8, thì bạn tính toán nó bằng cách gọi đệ quy 7 và cập nhật 0. Bước cuối cùng là trả về số Fibonacci được yêu cầuLoại bỏ các quảng cáoKhám phá thuật toán lặpĐiều gì sẽ xảy ra nếu bạn thậm chí không phải gọi hàm Fibonacci đệ quy? Bạn biết rằng hai số đầu tiên trong dãy là 0 và 1 và mỗi số tiếp theo trong dãy là tổng của hai số liền trước nó. Vì vậy, bạn chỉ cần tạo một vòng lặp cộng hai số trước đó, 7 và 8, với nhau để tìm số ở vị trí 8 trong dãyCác số màu tím được in đậm trong sơ đồ bên dưới biểu thị các số mới cần được tính toán và thêm vào 0 trong mỗi bước lặpĐể tính số Fibonacci tại vị trí 8, bạn lưu trữ hai số đầu tiên của dãy, 0 và 1, trong 0. Sau đó, tính liên tiếp các số tiếp theo cho đến khi bạn có thể trả về 3Tạo dãy Fibonacci trong PythonBây giờ bạn đã biết những kiến thức cơ bản về cách tạo dãy Fibonacci, đã đến lúc tìm hiểu sâu hơn và khám phá thêm các cách khác nhau để triển khai thuật toán cơ bản trong Python. Trong các phần sau, bạn sẽ khám phá cách triển khai các thuật toán khác nhau để tạo dãy Fibonacci bằng cách sử dụng đệ quy, lập trình hướng đối tượng Python và cả phép lặp Sử dụng đệ quy và lớp PythonCách tiếp cận đầu tiên của bạn để tạo chuỗi Fibonacci sẽ sử dụng lớp Python và đệ quy. Một lợi thế của việc sử dụng lớp so với hàm đệ quy được ghi nhớ mà bạn đã thấy trước đây là một lớp giữ trạng thái và hành vi (đóng gói) cùng nhau trong cùng một đối tượng. Tuy nhiên, trong ví dụ hàm, 0 là một đối tượng hoàn toàn riêng biệt, vì vậy bạn không có quyền kiểm soát đối với nóDưới đây là mã triển khai giải pháp dựa trên lớp của bạn
Đây là bảng phân tích về những gì đang xảy ra trong mã
Để thử mã này, hãy tiếp tục và lưu mã vào 88. Sau đó chạy mã này trong vỏ tương tác của bạn>>> 8Tại đây, bạn tạo rồi gọi một thể hiện của lớp 5 có tên là 50. Cuộc gọi đầu tiên sử dụng 51 làm đối số và trả về 51, đây là số Fibonacci thứ sáu vì bạn đang sử dụng các chỉ số dựa trên số khôngViệc triển khai thuật toán dãy Fibonacci này khá hiệu quả. Khi bạn có một thể hiện của lớp, thuộc tính 7 sẽ giữ các số đã được tính toán từ cuộc gọi này sang cuộc gọi khácTrực quan hóa thuật toán chuỗi Fibonacci đã ghi nhớBạn có thể hiểu một cách hiệu quả cách mỗi cuộc gọi đến hàm Fibonacci đệ quy được xử lý bằng cách sử dụng biểu diễn ngăn xếp cuộc gọi. Cách mỗi cuộc gọi được đẩy vào ngăn xếp và bật ra phản ánh chính xác cách chương trình chạy. Nó chứng minh rõ ràng việc tính toán số lượng lớn sẽ mất nhiều thời gian như thế nào nếu bạn không tối ưu hóa thuật toán Trong ngăn xếp cuộc gọi, bất cứ khi nào một hàm trả về kết quả, khung ngăn xếp biểu thị lệnh gọi hàm sẽ bật ra khỏi ngăn xếp. Bất cứ khi nào bạn gọi một chức năng, bạn thêm một khung ngăn xếp mới vào đầu ngăn xếp. Nói chung, thao tác này có độ phức tạp không gian là O(n) vì không có nhiều hơn n khung ngăn xếp trên ngăn xếp cuộc gọi tại một thời điểm Ghi chú. Có một trình chỉnh sửa mã thân thiện với người mới bắt đầu có tên là Thonny cho phép bạn hình dung ngăn xếp cuộc gọi của một hàm đệ quy theo cách đồ họa. Bạn có thể tham khảo Thonny. Trình chỉnh sửa Python thân thiện với người mới bắt đầu để tìm hiểu thêm Để trực quan hóa thuật toán Fibonacci đệ quy đã ghi nhớ, bạn sẽ sử dụng một tập hợp các sơ đồ biểu thị ngăn xếp cuộc gọi. Số bước được biểu thị bằng nhãn màu xanh lam bên dưới mỗi ngăn xếp cuộc gọi Giả sử bạn muốn tính F(5). Để làm điều này, bạn đẩy cuộc gọi đầu tiên đến chức năng vào ngăn xếp cuộc gọi Để tính F(5), bạn phải tính F(4) như được nêu trong quan hệ truy hồi Fibonacci, vì vậy bạn thêm lệnh gọi hàm mới đó vào ngăn xếp Để tính F(4), bạn phải tính F(3), vì vậy bạn thêm một lệnh gọi hàm khác vào ngăn xếp Để tính F(3), bạn phải tính F(2), vì vậy bạn thêm một lệnh gọi hàm khác vào ngăn xếp cuộc gọi Để tính F(2), bạn phải tính F(1), vì vậy bạn thêm nó vào ngăn xếp. Vì F(1) là trường hợp cơ sở, nó trả về ngay lập tức bằng 1 và bạn xóa cuộc gọi này khỏi ngăn xếp Bây giờ bạn bắt đầu thư giãn các kết quả theo cách đệ quy. F(1) trả lại kết quả cho hàm gọi của nó, F(2). Để tính F(2), bạn cũng cần tính F(0) Bạn thêm F(0) vào ngăn xếp. Vì F(0) là trường hợp cơ bản nên nó trả về ngay lập tức, cho bạn 0. Bây giờ bạn có thể xóa nó khỏi ngăn xếp cuộc gọi Kết quả gọi F(0) này được trả về F(2). Bây giờ bạn có những gì bạn cần để tính F(2) và xóa nó khỏi ngăn xếp Kết quả của F(2) được trả lại cho người gọi nó, F(3). F(3) cũng cần kết quả của F(1) để hoàn thành phép tính của nó, vì vậy bạn thêm nó trở lại ngăn xếp F(1) là trường hợp cơ sở và giá trị của nó có sẵn trong bộ đệm, vì vậy bạn có thể trả về kết quả ngay lập tức và xóa F(1) khỏi ngăn xếp Bạn có thể hoàn thành phép tính cho F(3), là 2 Bạn loại bỏ F(3) khỏi ngăn xếp sau khi hoàn thành phép tính của nó và trả lại kết quả cho người gọi nó, F(4). F(4) cũng cần kết quả của F(2) để tính giá trị của nó Bạn đẩy cuộc gọi đến F(2) vào ngăn xếp. Đây là nơi bộ đệm tiện lợi xuất hiện. Bạn đã tính toán nó trước đó, vì vậy bạn chỉ có thể truy xuất giá trị từ bộ đệm, tránh việc gọi đệ quy để tính lại kết quả của F(2). Bộ đệm trả về 1 và bạn xóa F(2) khỏi ngăn xếp F(2) được trả lại cho trình gọi của nó và bây giờ F(4) có tất cả những gì nó cần để tính giá trị của nó, đó là 3 Tiếp theo, bạn loại bỏ F(4) khỏi ngăn xếp và trả lại kết quả của nó cho người gọi cuối cùng và ban đầu, F(5) F(5) bây giờ có kết quả của F(4) và cũng là kết quả của F(3). Bạn đẩy một lệnh gọi F(3) vào ngăn xếp và bộ đệm tiện lợi sẽ hoạt động trở lại. Trước đó bạn đã tính F(3), vì vậy tất cả những gì bạn cần làm là truy xuất nó từ bộ đệm. Không có quy trình đệ quy để tính F(3). Nó trả về 2 và bạn xóa F(3) khỏi ngăn xếp Bây giờ F(5) có tất cả các giá trị mà nó cần để tính giá trị của chính nó. Bạn nhận được 5 bằng cách thêm 3 và 2, và đó là bước cuối cùng trước khi bạn loại bỏ lệnh gọi F(5) khỏi ngăn xếp. Hành động này kết thúc chuỗi lệnh gọi hàm đệ quy của bạn Ngăn xếp cuộc gọi hiện đang trống. Bạn đã hoàn thành bước cuối cùng để tính F(5) Biểu diễn các lệnh gọi hàm đệ quy bằng sơ đồ ngăn xếp cuộc gọi giúp bạn hiểu tất cả công việc diễn ra đằng sau hậu trường. Nó cũng cho phép bạn xem một hàm đệ quy có thể chiếm bao nhiêu tài nguyên Đặt tất cả các sơ đồ này lại với nhau cho phép bạn hình dung toàn bộ quá trình trông như thế nào Bạn có thể nhấp vào hình ảnh trên để phóng to các bước riêng lẻ. Nếu bạn không lưu vào bộ đệm các số Fibonacci đã tính toán trước đó, thì một số giai đoạn ngăn xếp trong sơ đồ này sẽ cao hơn nhiều, điều đó có nghĩa là chúng sẽ mất nhiều thời gian hơn để trả về kết quả cho người gọi tương ứng của chúng Sử dụng Phép lặp và Hàm PythonVí dụ trong các phần trước triển khai giải pháp đệ quy sử dụng ghi nhớ làm chiến lược tối ưu hóa. Trong phần này, bạn sẽ viết mã một hàm sử dụng phép lặp. Đoạn mã dưới đây triển khai phiên bản lặp lại của thuật toán dãy Fibonacci của bạn 5Bây giờ, thay vì sử dụng đệ quy trong 7, bạn đang sử dụng phép lặp. Việc triển khai thuật toán dãy Fibonacci này chạy trong thời gian tuyến tính O(n). Đây là một sự cố của mã
Để dùng thử mã này, hãy quay lại phiên tương tác của bạn và chạy mã sau >>> 1Việc triển khai 7 này khá tối thiểu. Nó sử dụng tính năng giải nén lặp lại để tính toán các số Fibonacci trong các vòng lặp, điều này khá hiệu quả về mặt bộ nhớ. Tuy nhiên, mỗi khi bạn gọi hàm với một giá trị khác của 8, nó phải tính toán lại chuỗi đó một lần nữa. Để khắc phục điều này, bạn có thể sử dụng các bao đóng và làm cho chức năng của bạn ghi nhớ các giá trị đã được tính toán giữa các lần gọi. Đi trước và cung cấp cho nó một thửPhần kết luậnDãy Fibonacci có thể giúp bạn hiểu rõ hơn về đệ quy. Trong hướng dẫn này, bạn đã học dãy Fibonacci là gì. Bạn cũng đã tìm hiểu về một số thuật toán phổ biến để tạo chuỗi và cách dịch chúng sang mã Python Dãy Fibonacci có thể là một bàn đạp tuyệt vời và là điểm khởi đầu để bước vào thế giới đệ quy, đây là một kỹ năng cơ bản cần có của một lập trình viên Trong hướng dẫn này, bạn đã học cách
Bạn cũng đã hình dung thuật toán đệ quy được ghi nhớ để hiểu rõ hơn về cách nó hoạt động đằng sau hậu trường. Để làm điều đó, bạn đã sử dụng sơ đồ ngăn xếp cuộc gọi Khi bạn nắm vững các khái niệm trong hướng dẫn này, kỹ năng lập trình Python của bạn sẽ được cải thiện cùng với tư duy thuật toán đệ quy của bạn Đánh dấu là đã hoàn thành Xem ngay Hướng dẫn này có một khóa học video liên quan do nhóm Real Python tạo. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn. Khám phá dãy Fibonacci bằng Python 🐍 Thủ thuật Python 💌 Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python Gửi cho tôi thủ thuật Python » Giới thiệu về Mandy Wong Mandy là một Pythonista vừa chớm nở muốn chia sẻ tình yêu và kiến thức của mình về Python và công nghệ phần mềm với thế giới. Cô ấy cũng là một TinyML + Kỹ sư dữ liệu trong đào tạo, một Muley và một vận động viên chơi gôn cạnh tranh hàng đầu bán thời gian đầy tham vọng » Thông tin thêm về MandyMỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là Aldren David Geir Arne Joanna Gia-cốp leodanis Sadie Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia Nâng cao kỹ năng Python của bạn » Bậc thầy Kỹ năng Python trong thế giới thực Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia Nâng cao kỹ năng Python của bạn » Bạn nghĩ sao? Đánh giá bài viết này Tweet Chia sẻ Chia sẻ EmailBài học số 1 hoặc điều yêu thích mà bạn đã học được là gì? Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. Nhận các mẹo để đặt câu hỏi hay và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi Chuỗi Fibonacci trong ví dụ Python là gì?Dãy Fibonacci là dãy số nguyên 0, 1, 1, 2, 3, 5, 8. Hai số hạng đầu tiên là 0 và 1. Tất cả các số hạng khác có được bằng cách cộng hai số hạng trước đó . Điều này có nghĩa là số hạng thứ n là tổng của số hạng thứ (n-1) và (n-2).
Python triển khai dãy Fibonacci như thế nào?Triển khai đệ quy . def fib(thuật ngữ) nếu thuật ngữ <= 1 trả lại (thời hạn) trở lại (fib(term-1) + fib(term-2)) # Thay đổi giá trị này để điều chỉnh số lượng các thuật ngữ trong chuỗi số_điều_kiện = 10 |