Độphứctạptính tốn Table of Contents • Giới thiệu • Tầm quan trọng lý luận • • o Ví dụ o Mẹo gộp hai thuậttoán Thế độ hiệu thuật toán? o Ví dụ o Lưu ý kích cỡ tập đầu vào o Tính tốn độ hiệu thuậttoán nào? Các khái niệm o • Lưu ý phân tích độphứctạpthuật tốn o • Xác định thời gian chạy dựa vào đánh giá cận Ví dụ Kết luận Nguồn bài: Topcoder Giới thiệu Trong viết giới thiệu tới bạn chủ đề độphứctạptính tốn Trước vào định nghĩa xác khái niệm, viết giải thích lý luận đằng sau khái niệm Tơi cho việc hiểu lý luận quan trọng thân định nghĩa khái niệm Tầm quan trọng lý luận Ví dụ Giả sử bạn phân cơng viết chương trình để xử lý tập liệu gồm nhiều ghi mà công ty bạn thu thập Bạn cài đặt hai thuậttoán kiểm tra chúng vài tập liệu khác Thời gian chạy thống kê bảng Số lượng ghi ThuậttoánThuậttoán Bảng 1: Thời gian chạy hai thuậttoán 1, Từ bảng ta đánh giá cách khơng thức thuật tốn tốt (vì thường ta ước lượng số lượng ghi cần xử lý) Với cơng ty kết luận dựa việc chạy thử chấp nhận Nhưng với người lập trình, tốt đánh giá thời gian chạy hai thuậttoán trước viết code chạy thử - sau cần cài đặt thuật tốn tốt Các kỳ thi lập trình đòi hỏi việc đánh giá tương tự: kích cỡ tập liệu cho trước đề Giả sử ta nghĩ thuậttoán Câu hỏi cần đặt trước bắt tay vào cài đặt là: thuật tốn có đáng để cài đặt khơng? Liệu chạy test lớn thời gian cho phép khơng? Nếu ta nghĩ vài thuậttoán khác, nên chọn thuật để cài đặt? Các câu hỏi dẫn tới câu hỏi cốt lõi hơn: Làm để so sánh hai thuật tốn với nhau? Quay trở lại ví dụ 1, ta ước lượng số ghi vượt 1000, thuậttoán chạy nhanh nhiều lần thuật tốn Nói cách khác, xét tất tập liệu có thể, thuật tốn chạy tốt hầu hết trường hợp Có thể kết luận hầu hết trường hợp - cho trước thuật toán, thuật tốn gần ln ln tốt hơn, hai xấp xỉ tốt Như vậy, định nghĩa độ tốt thuậttoán dựa vào đánh giá độ hiệu chạy toàntập liệu Đánh giá ý tưởng đằng sau định nghĩa cụ thể mà đề cập sau Mẹo gộp hai thuậttoán Nếu đối chiếu với hai thuật tốn ví dụ 1, khơng khó để thấy có thuật tốn với thời gian chạy tương tự với chúng bảng Số lượng ghi Thuậttoán 0.00s Bảng 2: Thời gian chạy thuậttoán Ý tưởng thuâttoán 3: số lượng ghi nhỏ ta áp dụng thuật tốn 1, ngược lại áp dụng thuậttoán Ý tưởng tương tự thường áp dụng vào thực tế Một ví dụ hàm xếp sort() cung cấp thư viện ngôn ngữ lập trình thường cài đặt theo thuật tốn QuickSort với nhiều cải tiến, ví dụ: • Nếu số lượng phần tử nhỏ, chạy thuậttoán xếp chèn InsertSort (vì InsertSort chạy nhanh với tập liệu kích thước nhỏ) • Nếu vị trí phần tử chốt khơng tốt, chuyển sang chạy thuậttoán xếp trộn MergeSort Thế độ hiệu thuật tốn? Ví dụ Giả sử bạn có đoạn mã sau: for (int i = 0; i < N; i++) for (int j = i + 1; j < N; j++) if (A[i] > A[j]) swap(A[i], A[j]); (Đây thực cách cài đặt thuậttoán MinSort) Giả sử cho mảng liệu đầu vào (mảng A số phần tử N), ta tính xác số bước chạy thuật tốn đầu vào cho Ta chí tính xác số lệnh thực thi vi xử lý ta muốn (ND: chuyển đoạn mã C+ + thành mã Assembly) Tuy nhiên, có nhiều giá trị mà liệu đầu vào nhận nên việc tính tốn số bước với khả đầu vào Thực tế dẫn ta tới câu hỏi quan trọng hơn: đánh giá quan trọng độ hiệu mà cần tới gì? Thơng thường tốc độ chạy thuậttoán trường hợp xấu - ta cần tìm đánh giá cận tốc độ chạy thuậttoán Tuy nhiên, là trường hợp xấu nhất? Một cách đơn giản để làm cho thuật tốn chạy chậm tăng kích cỡ đầu vào Vì cận số phần tử bị chặn đề bài, câu hỏi quan trọng là: tập đầu vào xấu tập có số phần tử tập nào? Khi tăng kích cỡ tập đầu vào độphứctạp trường hợp xấu tăng nào? Lưu ý kích cỡ tập đầu vào Hiểu xác "kích cỡ tập đầu vào" đại lượng gì? Theo định nghĩa thống, kích cỡ tập đầu vào viết thành tập hữu hạn ký tự (với 02 'ký tự') Trong ta coi tập ký tự số tự nhiên từ tới 255 Như "kích cỡ tập đầu vào" tính số bytes tệp chứa liệu đầu vào (input file) Thường phần liệu số (hoặc vài số), mà kích cỡ tập đầu vào tỉ lệ thuận với số Chẳng hạn ví dụ 2, ta có số tự nhiên N mảng với N số integer Kích cỡ theo đơn vị bytes file đầu vào xấp xỉ 5N (phụ thuộc vào hệ điều hành cấu trúc máy tính, ln tuyến tính với N ) Trong trường hợp này, ta chọn số (hoặc số) để biểu diễn kích cỡ tập đầu vào Vì nói tốn có mảng / chuỗi, kích cỡ tập đầu vào độ dài mảng / chuỗi đó, nói toánđồ thị ta biểu thị hai đại lượng số lượng đỉnh số lượng cạnh, Với cách tiếp cận đó, kể từ cuối viết ta ký hiệu N kích cỡ tập đầu vào Một trường hợp cần lưu ý viết số N ta cần log(N) khoảng trống (ví dụ để viết 123456 hệ số 10 ta cần log10(123456) chữ số) Cần phân biệt hai đại lượng - với thuậttoán kiểm tra số nguyên tố đơn giản có độphứctạp đa thức độ lớn số kiểm tra số lượng chữ số số đó! Nếu bạn chưa gặp khái niệm độphứctạp đa thức khơng cần lo lắng khái niệm giải thích phần sau Tính tốn độ hiệu thuật tốn nào? Nhắc lại cho trước liệu đầu vào, ta đếm số bước thực phép toánthuậttoán cách mơ bước chạy thuật tốn liệu cho Giả sử ta tiến hành đếm với tất liệu có kích thước tối đa N Ký hiệu f(N) số bước cần thực nhiều (trường hợp xấu nhất) Hàm f gọi độphứctạp thời gian, ngắn gọn thời gian chạy thuật tốn Nói cách khác, ta có liệu vào với kích cỡ N , việc thực thuật tốn tối đa f(N) bước Quay trở lai thuậttoán ví dụ Tập đầu vào xấu có N phần tử tập nào? Nói cách khác, số mảng có N phần tử, mảng khiến cho thuậttoán phải thực nhiều bước nhất? Từ đoạn mã thuật tốn ta thấy: • Bước thứ thực N lần Bước thứ hai thứ ba thực N(N−1)2 lần Bước thứ tư thực nhiều N(N−1)2 • lần Dễ thấy phần tử mảng A xếp theo chiều giảm dần từ đầu, bước thứ luôn thực Vì thuật tốn chạy 3N(N−1)2+N=1.5N2−0.5N bước Vì thuật tốn có số bước tối đa f(N)=1.5N2−0.5N Có thể thấy việc xác định xác hàm f cho chương trình phứctạp khó khăn Thêm vào đó, nhiều trường hợp dạng xác hàm f khơng cần thiết Trong tính tốn giá trị −0.5N bỏ qua, N lớn 0.5N nhỏ nhiều so với 1.5N2 không ảnh hưởng lớn tới thời gian chạy Mệnh đề "f(N) xấp xỉ 1.5N2" cho ta tất thông tin mà ta cần Tiếp theo thấy rằng, so sánh thuậttoán với thuậttoán khác để giải tốn, số 1.5 khơng thật quan trọng Xét hai thuật tốn, có thời gian chạy N2 có thời gian chạy 0.0001N3 Dễ nhận thấy với N>1000 thuậttoán chạy nhanh - N tăng, khoảng cách độ hiệu hai thuậttoán trở nên rõ ràng Trong thuậttoán giải tốn với N=20000 thời gian tính giây, thuật tốn thứ hai phải tới vài phút máy tính đại Sự khác biệt xảy hai thuật tốn có thời gian chạy tăng tiệm cận nhanh so với thời gian chạy thuật tốn lại (nói cách khác, N đủ lớn để kết phép tính giới hạn lim tỷ lệ hai đại lượng ∞ ND: tác giả không nói rõ việc so sánh độphứctạp theo phép tính giới hạn, cần hiểu khái niệm tiệm cận có nghĩa kích cỡ đầu vào đủ lớn Như tiệm cận nhanh có nghĩa nhanh đầu vào đủ lớn) Bất kể số nhận giá trị nào, thuật tốn có thời gian chạy tỷ lệ (thuận) với N2 luôn hiệu thuật tốn khác có thời gian chạy tỷ lệ với N3 hầu hết trường hợp tập đầu vào Nhận định ý tưởng chủ đạo để xây dựng định nghĩa thức khái niệm Các khái niệm Gọi f,g hàm số dương không giảm tập số nguyên dương (lưu ý hàm thời gian chạy thỏa mãn điều kiện này) Ta nói "f(N) thuộc O(g(N))" (cách đọc: "f thuộc O-lớn g") tồn giá trị c N0 thỏa mãn điều kiện sau: ∀N>N0;f(N) D) ) j++; if (A[i] - A[j] == D) return 1; } Thoạt nhìn ta đánh giá thuật tốn có cận O(N2) - vòng lặp chạy N lần, lần tăng biến j tối đa N lần Phân tích kỹ hơn, ta thấy cận có đánh giá tốt O(N) - thật tổng thể số lần chạy câu lệnh j++ tồn thuật tốn khơng vượt q N lần Mệnh đề "thuật tốn O(N2) " mệnh đề Tuy nhiên việc nói "thuật tốn O(N) " ta cung cấp nhiều thông tin thuật tốn Kết luận Chúng ta cách viết cận (trên, dưới) theo độphứctạptínhtoánthuậttoán Ta chứng minh cận thuộc tính thường hiệu để đánh giá thuậttoán Trong phần sau phân tích làm để ước lượng độphứctạptính tốn thuật tốn Như ta thấy Ví dụ việc phân tích trở nên khó khăn Một nguyên nhân khác làm cho việc phân tích khó khăn thuật tốn đệ quy Các vấn đề xử lý phần viết