Bài 10.5 - Kỹ thuật memoization trong Python
Free
Khóa học Python từ Cơ bản đến Nâng cao
Chương 1: Làm quen với Python + Ôn tập I/O, biến, kiểu dữ liệu
Chương 2: Câu lệnh rẽ nhánh, vòng lặp, hàm
Chương 3: Xử lý chuỗi và danh sách nâng cao
Chương 4: Bài kiểm tra Python cơ bản + sửa bài
Chương 5: Duyệt mảng, tìm max/min, đếm
Chương 6: Thuật toán sắp xếp
Chương 7: Prefix Sum + Two Pointers
Chương 8: Backtracking cơ bản
Chương 9: Ôn tập thuật toán cơ bản + kiểm tra
Chương 10: Dynamic Programming cơ bản
Chương 11: Đệ quy và DP nâng cao
Chương 12: Đồ thị cơ bản – DFS, BFS
Chương 13: Đồ thị nâng cao – Dijkstra + Topo sort
Chương 14: Cây – Tree traversal + LCA
Chương 15: Bitmask – Kỹ thuật đại số
Chương 16: Số học + Modular Arithmetic
Chương 17: Class
Chương 18: File và Exception
Bài 10.5 - Kỹ thuật memoization trong Python
Memoization là kỹ thuật lưu trữ kết quả các hàm đã tính trước đó để tránh tính lại, từ đó tăng tốc độ chương trình rõ rệt, đặc biệt với các bài toán đệ quy.
Ví dụ vấn đề: Fibonacci đệ quy thuần
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
Chạy fib(30) sẽ rất chậm vì hàm fib(n) bị gọi lại rất nhiều lần với cùng tham số.
Cách dùng memoization thủ công
Ta dùng một dictionary để lưu kết quả đã tính:
def fib_memo(n, memo={}):
if n in memo:
return memo[n]
if n <= 1:
memo[n] = n
else:
memo[n] = fib_memo(n-1, memo) + fib_memo(n-2, memo)
return memo[n]
Ví dụ:
print(fib_memo(30)) # Output: 832040, rất nhanh
Từ O(2^n) giảm còn O(n), tiết kiệm hàng triệu phép tính với n lớn.
Cách dùng functools.lru_cache trong Python
Thư viện functools có sẵn decorator để tự động memo hóa:
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
Ví dụ:
print(fib(50)) # Output: 12586269025
@lru_cachegiúp memo hóa hàm đơn giản chỉ bằng 1 dòng.
Memoization với bài toán khác: Tính số cách leo cầu thang
Đề bài: Mỗi lần có thể bước 1 hoặc 2 bậc. Có bao nhiêu cách để leo lên n bậc?
def climb(n, memo={}):
if n in memo:
return memo[n]
if n <= 1:
return 1
memo[n] = climb(n-1, memo) + climb(n-2, memo)
return memo[n]
Thử chạy:
print(climb(10)) # Output: 89
Khi nào nên dùng memoization?
- Hàm đệ quy có gọi lại nhiều lần cùng tham số
- Bài toán có tính chồng lặp trạng thái
- Không cần phải tối ưu bộ nhớ quá khắt khe
Không nên dùng memoization khi:
- Bài toán không có lặp lại trạng thái
- Cần tính toán chính xác từng bước (ví dụ yêu cầu thứ tự cụ thể)
- Tối ưu về bộ nhớ (vì memo hóa chiếm RAM)
Tổng kết
- Memoization là kỹ thuật cực kỳ hữu ích khi viết các bài toán đệ quy.
- Có thể dùng
dicthoặc@lru_cacheđều được. - Ghi nhớ để dùng cho các bài như: Fibonacci, leo cầu thang, LCS, LIS, subset sum, knapsack,...
Khóa học liên quan
Giảm giá!
3300000
4500000
Học Ngay
Comments