Cac ky thuat co ban de tang toc chuong trinh

10 1 0
Cac ky thuat co ban de tang toc chuong trinh

Đang tải... (xem toàn văn)

Thông tin tài liệu

CÁC KỸ THUẬT CƠ BẢN ĐỂ TĂNG TỐC CHƯƠNG TRÌNH Việc lưu trữ thông tin cần nhớ sao cho có thể lấy lại chúng một cách nhanh nhất là một trong các kỹ năng cơ bản đầu tiên để có thể có một chương trình hiệu[.]

CÁC KỸ THUẬT CƠ BẢN ĐỂ TĂNG TỐC CHƯƠNG TRÌNH Việc lưu trữ thơng tin cần nhớ cho lấy lại chúng cách nhanh kỹ để có chương trình hiệu Tuy việc nhớ lưu trữ lại địi hỏi nhạy bén tốn học học sinh Điều lại hình thành sau học sinh tiếp xúc với hệ thống toán tổ chức cẩn thận Hệ thống giúp học sinh xây dựng thói quen tư kỹ thuật lập trình Dưới đây, tơi trình bày hệ thống tập phân loại kỹ lưỡng qua nhiều năm giảng dạy nhằm mục đích hình thành cho em kỹ nói Kỹ thuật nhớ Đây kỹ thuật đơn giản, thông tin cần nhớ lưu trữ vào mảng vị trí thích hợp Khi cần, việc lấy thơng tin khoảng thời gian O(1) Bài toán 1: Cho mảng n số nguyên dương a1, a2, , an (n≤106, ai≤106) số nguyên dương S (S≤106) Hãy đếm xem có cặp (ai,aj) thỏa mãn ai+aj=S Thuật toán O(n2) đơn giản đề giải toán là: ds:=0; for j:=1 to n for i:=1 to j-1 if a[i]+a[j]=S then ds:=ds+1; writeln(ds); Để cải tiến, xem xét đẳng thức điều kiện a[i]+a[j]=S Nếu j cố định a[i]=S-a[j] cố định Và thấy vòng lặp bên chẳng qua đếm xem có phần tử S-a[j] Vậy ta nhớ số lượng xem khơng cần vịng lặp bên để đếm nữa! Để ý đến điều kiện đầu 1≤a[i]≤10 ta hoàn tồn lập mảng nhớ: var c: array[1 1000000] of longint; với c[x] số lượng phần tử x xuất Ta có chương trình hiệu để giải sau: fillchar(c,sizeof(c),0); for j:=1 to n begin if (S-a[j]>0) then inc(ds,c[S-a[j]]); inc(c[a[j]]); end; Thuật tốn có độ phức tạp O(n) đáp ứng dược yêu cầu toán đề mặt thời gian Tuy nhiên thấy chi phí nhớ tăng lên Có thể nhận xét điều để học sinh thấy muốn có chương trình chạy nhanh chi phí nhớ phải tốn Bài toán 2: Cho dãy số a1, a2, , an (1≤n≤106,  109 ) Hãy tìm dãy dãy số cho gồm phần tử liên tiếp cho tổng phần tử dãy lớn Đây toán điển hình cho việc cải tiến chương trình cho mức độ hiệu ngày cao Ta xét thuật tốn đơn giản để giải tốn có độ phức tạp O(n2): ds:=0; for j:=1 to n for i:=1 to j begin T:=0; for k:=I to j T:=T+a[k]; if T>ds then ds:=T; end; Thuật toán hoàn toàn tự nhiên Tuy nhiên với độ phức tạp O(n3) cho kết thời gian giây n≤100 Cần phải có thuật tốn tinh tế Nhận xét để tính tổng T=a[i]+a[i+1]+…a[j] ta viết T=(a[1]+a[2]+…+a[j])-(a[1]+a[2]+…+a[i-1]) = s[j]-s[i-1] s[k]=a[1]+…a[k] Bằng cách chuẩn bị trước mảng S O(n) ta thay vịng lặp thuật tốn lệnh Ta có chương trình cải tiến sau: ds:=a[1]; s[0]:=0; for i:=1 to n s[i]:=s[i-1]+a[i]; for j:=1 to n for i:=1 to j if s[j]-s[i-1]>ds then ds:=s[j]-s[i-1]; Độ phức tạp thuật toán thứ hai O(n2) dùng thuật toán giải tốn với n≤2000 Để tăng tốc chương trình nữa, đến lại sử dụng kỹ thuật nhớ toán Xét vòng lặp (i) Nếu j cố định vịng lặp chẳng qua tìm số I để s[j]-s[i-1] đạt giá trị lớn Điều tương đương với việc tìm giá trị nhỏ s[i-1] với i=1,2,…,j tìm giá tị nhỏ s[0],s[1],…,s[j-1] Bằng cách dùng thêm biến để lưu giá trị nhỏ có thuật toán O(n) đáp ứng yêu cầu toán sau: s[0]:=0; for i:=1 to n s[i]:=s[i-1]+a[i]; ds:=a[1]; min:=0; for j:=1 to n begin if s[j]-min>ds then ds:=s[j]-min; if s[j]ds then ds:=b[k]-min if min>b[k] then min:=b[k]; end; end; Độ phức tạp thuật toán O(m2n) Một điều thú vị kỹ thuật cố định hàng hàng kỹ thuật phổ biến để đưa việc giải toán hai chiều thành toán chiều Bài toán 4: Cho dãy nhị phân độ dài n Hãy đếm xem có dãy dãy cho có số lượng số số lượng số Với việc làm quen kỹ thuật tính tổng đoạn [i,j] nhanh chóng đưa thuật toán O(n2) để giải toán sau: dem:=0; for j:=1 to n for i:=1 to j if s1[j]-s1[i-1]=s0[j]-s0[i-1] then inc(dem); Ở s1[k], s0[k] số lượng số 1, số lượng số đoạn [1,k] Hai mảng chuẩn bị trước thời gian O(n) Để cải tiến chương trình trên, sử dụng kỹ thuật hay dùng toán học phân li ẩn số: Nhận xét biểu thức s1[j]-s1[i-1]=s0[j]-s0[i-1] tương đương với s1[j]-s0[j]=s1[i-1]-s0[i1] (chuyển số hạng có j vế, số hạng có i về cịn lại) Ta đến kết luận quan trọng j cố định, biến dem tăng lượng số lượng vị trí i trước có s1[i]-s0[i]=s1[j]-s0[j] Sử dụng kỹ thuật mảng nhớ toán có thuật tốn O(n): dem:=0; c[0]:=1; for j:=1 to n begin inc(dem,c[s1[j]-s0[j]]); inc(c[s1[j]-s0[j]]); end; Kỹ thuật trì mảng xếp Trong kỹ thuật nhớ, lần lấy thông tin nhớ để xử lý đích xác phần tử cần lấy thơng qua số Tuy vậy, số trường hợp khác phần tử nhớ cần lấy không xuất tường minh (vì khơng đủ nhớ chứa nó) mà thường nằm dải giá trị Nếu trì mảng nhớ dạng xếp tăng giảm dần kỹ thuật tăng tốc hay gặp kỹ thuật tìm kiếm nhị phân đơn giản dị tuyến tính mảng nhớ Bài toán 5: Cho dãy a1, a2, …, an Hãy đếm xem có dãy dãy cho gồm số hạng liên tiếp mà có tổng Bằng cách thử tất dãy có ta có thuật tốn O(n2) sau: dem:=0; for j:=1 to n for i:=1 to j if s[j]=s[i-1] then inc(dem); Tất nhiên, giá trị a[i] nhỏ kéo theo giá trị s[i] nhỏ kỹ thuật nhớ phần áp dụng Tuy nhiên, a[i] lớn khơng thể làm khơng đủ nhớ (!!!) Nhận xét thông tin cần nhớ mảng s mảng xếp tăng dần tốn đơn giản đếm xem có cặp (s[i], s[j]) Sau xếp lại mảng S Việc đếm tính O(n) sau: u:=1; for v:=2 to n+1 if s[v]>s[u] then begin k:=v-u; inc(dem,(k-1)*k div 2); u:=v; end; Ở s[n+1]=vc phần tử đủ lớn để cầm canh Độ phức tạp thuật toán tổng cộng cho phần O(nlogn) chủ yếu phụ thuộc vào thuật toán xếp lựa chọn Bài toán 6: Cho dãy a1, a2, …, an Hãy tìm dãy tăng dài (các phần tử dãy tăng không thiết liên tiếp) dãy cho Nếu gọi f[i] độ dài dãy tăng dài kết thúc a[i] ta có cơng thức truy hồi sau:  f [0]    f [i]  max f [k ] : k  i, a[k ]  a[i]  Ở a[0]=-vc số đủ nhỏ để cầm canh Nếu biết f[i] đáp số tốn max{f[i]: i=1,2,…,n} Để tính f[i], ,một thuật tốn O(n2) thường dùng sau: f[0]:=0; for i:=1 to n begin f[i]:=1; for k:=i-1 downto if (a[k]

Ngày đăng: 15/02/2023, 19:32

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan