You are on page 1of 63

Đệ Quy

(Recursion)

Trịnh Tấn Đạt


Khoa CNTT - Đại Học Sài Gòn
Email: trinhtandat@sgu.edu.vn
Website: https://sites.google.com/site/ttdat88/
Nội dung
▪ Khái niệm
▪ Phân loại
▪ Các vấn đề đệ quy thông dụng
▪ Đệ quy và chia để trị
▪ Bài toán tháp hà nội
▪ Đệ quy và quy lui (option)
▪ Bài toán Edit distance (option)
▪ Bài toán Closet pairs of points (option)
▪ Bài Tập
Đệ Quy
▪ Đệ quy là kỹ thuật đưa bài toán hiện tại về một bài toán cùng loại, cùng tính chất
(đồng dạng) nhưng ở cấp độ thấp hơn. Quá trình này tiếp tục cho đến khi bài
toán được đưa về một cấp độ mà tại đó có thể giải được. Từ cấp độ này ta lần
ngược lại để giải các bài toán ở cấp độ cao hơn cho đến khi giải xong bài toán ban
đầu.

▪ Ví dụ: Định nghĩa n giai thừa:


n! = 1*2*3*4*5*…*n → định nghĩa tự nhiên
n*(n-1)! với 0!=1 → định nghĩa bằng đệ quy
Đệ Quy
Các ứng dụng
▪ Hình học fractal
▪ Game candy crush
▪ Structure “Tree”
▪ …

Koch snowflake Candy Crush


Đệ Quy - Khái niệm
▪ Kỹ thuật đệ quy: là kỹ thuật định nghĩa một khái niệm có sử dụng
chính khái niệm đang cần định nghĩa.
▪ Hàm đệ quy: là hàm mà trong thân của nó có lệnh gọi lại chính nó
dành cho đối tượng ở cấp thấp hơn.
▪ Ví dụ: Hàm tính n!

… Hàm(…)
{


Lời gọi Hàm



}
Đệ quy
S = 1+2+3+…+n
▪ Hai yếu tố cần để tiến hành
một phương thức đệ quy là:
o Có điều kiện dừng (phần cơ sở,
phần neo): Xác định quy luật
của phương thức và tìm giá trị
cụ thể khi thỏa mãn một điều
kiện nhất định.
Nếu hàm đệ quy không có phần
này thì hàm sẽ bị lặp vô hạn và
sinh lỗi khi thực hiện.
o Phương thức đệ quy: Phương
thức đệ quy sẽ gọi lại chính nó
nhưng dành cho cấp độ thấp
hơn. cho đến khi nó trả về điều
kiện dừng ở bước 1.
Ví dụ Tính giai thừa n!
#include <iostream>
using namespace std;
int factorial(int n) {
if (n == 1) //phần neo
Vòng lặp vô tận return 1;
else
#include <iostream> return (n * factorial(n - 1)); // phần đệ quy
using namespace std; }
int main() {
void p() { cout << "Giai thua cua 5 la:" << factorial(5);
cout << "hello" << endl; return 0;
p(); }

}
int main() {
p();
return 0;
}
Đệ Quy
❖ Cách viết hàm đệ quy
▪ Định nghĩa tác vụ đệ quy thế nào thì viết hàm đệ quy như
vậy. Xét 2 trường hợp neo (thực hiện không đệ quy) và
trường hợp đệ quy.
▪ Ví dụ: Chuyển các định nghĩa sau về dạng đệ quy:
S(n) = 1+2 +3+… + n
S(n) = 1+1/2 + 1/3 + ... + 1/n
S(n) = 1*2 + 2*3+ 3*4 + 4*5 +.….+ n(n+1)
Bài toán dãy số Fibonacci
▪ Fibonacci (1180 - 1250) được biết đến nhiều nhất với dãy số mang tên
ông - dãy số Fibonacci.
▪ Dãy số này xuất hiện trong bài toán dưới đây viết trong cuốn Liber
Abaci: "Trong một năm, bắt đầu chỉ từ một đôi thỏ, bao nhiêu đôi
thỏ sẽ được sinh ra nếu mỗi tháng một đôi thỏ sinh được một đôi thỏ
con và cặp thỏ này lại đẻ được từ tháng thứ hai trở đi?“
▪ Dãy số Fibonacci có nguồn gốc từ bài toán trên là một dãy sao cho mỗi
số hạng, kể từ sau số hạng thứ nhất, bằng tổng của hai số đứng ngay
trước nó. Dãy số đó là:
1,1,2,3,5,8,13,21,34,55,89,144....
Bài toán dãy số Fibonacci
▪ Dãy số Fibonacci:
F(n)= F(n-1)+F(n-2) (phần đệ quy)
F(n)=1 với n<=2 (phần neo).
▪ Hàm đệ quy tính số thứ n trong dãy số Finbonacci
Bài tập Viết hàm đệ quy cho các bài toán
Bài tập Viết hàm đệ quy cho các bài toán
Đệ Quy
❖ Phân loại đệ quy (chỉ là hình thức)
▪ Đệ quy tuyến tính: trong thân hàm có duy nhất một lời gọi hàm
gọi lại chính nó một cách tường minh.
▪ Đệ quy nhị phân: Trong thân hàm có hai lời gọi hàm gọi lại
chính nó một cách tường minh.
▪ Đệ quy lồng: Tham số trong lời gọi hàm là một lời gọi đệ quy.
▪ Đệ quy hỗ tương: Trong thân hàm này có lời gọi hàm tới hàm kia
và bên trong thân hàm kia có lời gọi hàm tới hàm này
▪ Đệ quy phi tuyến: Trong thân hàm có lời gọi hàm lại chính nó
được đặt bên trong thân vòng lặp.
Đệ quy tuyến tính
▪ Đệ quy tuyến tính: bên trong thân hàm chỉ gọi hàm đệ quy 1 lần
▪ Cấu trúc hàm dạng đệ quy tuyến tính
Đệ quy nhị phân
▪ Đệ quy nhị phân: bên trong thân hàm gọi hàm đệ quy 2 lần.
▪ Cấu trúc hàm dạng đệ quy nhị phân
Đệ quy lồng
▪ Hàm được gọi là đệ quy lồng nếu tham số trong lời gọi hàm là một lời gọi đệ quy.
▪ Cấu trúc hàm dạng đệ qui lồng
Đệ quy hỗ tương
▪ Trong đệ quy tương hỗ thì thường có 2 hàm, và trong thân của hàm này có lời gọi
của hàm kia , điều kiện dừng và giá tri trả về của cả hai hàm có thể giống nhau hoặc
khác nhau.

Cấu trúc hàm dạng đệ quy

Hàm nguyên mẫu


(Function
Prototype)
Function Prototype
▪ Hàm nguyên mẫu cung cấp cho trình
biên dịch (compiler) tên của hàm,
kiểu dữ liệu mà hàm trả về, số lượng
các đối số mà hàm cần cung cấp,
kiểu dữ liệu và thứ tự của các đối số
đó.
▪ Hàm nguyên mẫu giúp cho trình
biên dịch xác nhận các lời gọi hàm
mà chưa cần định nghĩa hàm đó.
Đệ quy phi tuyến
▪ Đệ quy phi tuyến: nếu bên trong thân hàm có lời gọi lại chính nó được đặt bên trong
thân của vòng lặp.
▪ Cấu trúc hàm dạng đệ quy phi tuyến
#include <stdio.h>
Ví dụ 1 int tinhXn(int);
int tinhXn(int n)
{
if(n==1)
return 1;
int temp = 0;
for (int j= 1; j< n ; j++)
temp = temp + tinhXn(j);
return n*temp;
}
int main()
{
int n = 4;
printf("ket qua : %d\n",tinhXn(n));
return 0;
}
#include <stdio.h>

Ví dụ 2
#include <iostream>
using namespace std;
long U(int); // protype
long G(int);// protype
Tính các dãy số sau long U (int n)
{
if (n<5) return n;
return U(n-1) + G(n-2);
}
long G(int n)
{
if (n<8) return n-3;
return U(n-1) + G(n-2);
}

int main()
{ int n; cout <<"input n:";
cin >> n;
cout<< "U(n)=" << U(n) << endl;
cout<< "G(n)=" << G(n) << endl;
system("pause");
return 0;
}
Ví dụ 3 #include <stdio.h>
#include <iostream>
using namespace std;
int digitcount(int n)
Đếm số chữ số của số nguyên {
dương n. n= abs(n);
if(n<10)
Ví dụ: n=123456789 → kq = 9 return 1;
return 1+ digitcount(n/10);
}
int main()
{ int n;
cout <<"input n:";
cin >> n;
cout<< "count = " << digitcount(n) << endl;
system("pause");
return 0;
}
Đệ quy
❖ Khử đệ quy dùng vòng lặp hoặc Stack
❖ So sánh đệ quy và vòng lặp
▪ Đệ quy
o Ưu điểm: Chương trình gắn gọn, dễ hiểu, giải quyết được nhiều vấn đề phức tạp, Hầu hết các ngôn
ngữ lập trình đều hỗ trợ kỹ thuật đệ quy
o Nhược điểm:
• Các hàm đệ quy được gọi lồng nhau dẫn đến việc khó debug, khi debug cần phải nắm rõ
mình đang ở mức đệ quy nào.
• Tốc độ xử lí chậm cũng vì lì do liên tục gọi các hàm lồng nhau.
• Với input lớn, hàm đệ quy có thể dẫn đến việc bùng nổ trong việc gọi hàm, dẫn đến tình
trạng tràn bộ nhớ stack (stack overflow)
▪ Vòng lặp
o Ưu điểm: chỉ có một vòng duy nhất được gọi ra và ta sẽ không phải lo nghĩ gì về vấn đề tràn bộ
nhớ Stack
o Nhược điểm: code xử lý sẽ viết dài và phức tạp hơn.
Các bước tìm giải thuật đệ quy cho bài toán
▪ Bước 1: Thông số hóa bài toán.

▪ Bước 2: Tìm các trường hợp cơ bản (phần neo) cùng giải thuật tương
ứng cho các trường hợp này.

▪ Bước 3: Tìm giải thuật giải trong trường hợp tổng quát (phần đệ quy)
bằng cách phân rã bài toán theo kiểu đệ quy
Thông số hóa bài toán
▪ Chuyển bài toán cần giải thành bài toán tổng quát.
▪ Tìm ra các thông số cho bài toán tổng quát, đặc biệt là nhóm các thông số biểu thị kích
thước của bài toán.
▪ Ví dụ:
o Bài toán tính n!: n là tham số tổng quát, biểu thị kích thước bài toán
o Bài toán tính giá trị Ackermann’s: n và m là tham số tổng quát, biểu thị kích thước bài
toán.
Xác định thành phần cơ bản của bài toán
▪ Xác định trường hợp neo của bài toán tổng quát.

▪ Đây là các trường hợp tương ứng với các giá trị biên củac ác biến điều khiển mà giải
thuật giải không đệ quy. Thông thường trong trường hợp này giải thuật rất đơn giản.

▪ Ví dụ:
o Giá trị giai thừa của n=0 hoặc n=1 là 1
o Giá trị hàm U(n) = n, với n<5 (ví dụ 2)
o Giá trị hàm Ackerman = n+1, với m=0 và n>0
Phân rã bài toán theo phương thức đệ quy
▪ Tìm giải thuật giải bài toán trong trường hợp tổng quát bằng cách phân chia nó thành
các thành phần:
o hoặc có giải thuật không đệ quy.
o hoặc là bài toán trên nhưng có kích thước nhỏ hơn (có đệ quy).
▪ Mục đích của bước thực hiện này là tìm giải thuật để giải bài toán theo hướng đệ quy
với giá trị tham số tổng quát

▪ Ví dụ
Ví dụ
▪ Hàm tìm Max trong Array dùng đệ quy

int max2So (int x, int y)


{
return x>y?x:y;
}

int timMAX_Dequy(int a[],int n)


{
if (n == 1)
return a[0];
else
return max2So(timMAX_Dequy(a,n-1),a[n-1])
}
Khử đệ quy
▪ Là quá trình chuyển đổi 1 giải thuật đệ quy thành giải thuật không đệ quy.
▪ Chưa có giải pháp cho việc chuyển đổi này một cách tổng quát. Ta thường khử đệ
quy cho đệ quy tuyến tính.
▪ Cách tiếp cận:
o Dùng quan điểm đệ quy để tìm giải thuật cho bài toán.
o Mã hóa giải thuật đệ quy.
o Khử đệ quy để có giải thuật không-đệ-quy.

▪ Có 2 cách thường dùng :


▪ Khử đệ quy bằng vòng lặp
▪ Khử đệ quy dùng Stack
Khử đệ quy bằng vòng lặp
▪ Ý tương: Lưu lại các trị của các lần tính toán trước làm dữ liệu cho việc tính toán của
lần sau.
Các vấn đề đệ quy thông dụng
▪ Hệ thức truy hồi: Hệ thức truy hồi của 1 dãy An là công thức biểu diễn phần tử An
thông qua 1 hoặc nhiều số hạng trước của dãy.
Các vấn đề đệ quy thông dụng
▪ Chia để trị
o Chia bài toán thành nhiều bài toán con.
o Giải quyết từng bài toán con.
o Tổng hợp kết quả từng bài toán con để ra lời giải.
Chia để trị
Ví dụ: Tìm kiếm nhị phân trên mảng tăng dần
Chia để trị
Ví dụ: Tìm kiếm nhị phân trên mảng tăng dần
// Hàm tìm kiếm nhị phân sử dụng giải thuật khử đệ quy
// Hàm tìm kiếm nhị phân sử dụng giải thuật đệ quy int binarySearch(int arr[], int n, int x)
int binarySearch(int arr[], int l, int r, int x) {
{ int r = n - 1; // chỉ số phần tử cuối
if (r >= l) int l = 0; // Chỉ số phần tử đầu tiên
{ while (r >= l)
int mid = l + (r - l) / 2; {
// Tương đương (l+r)/2 nhưng ưu điểm tránh tràn số khi l,r lớn int mid = l + (r - l) / 2;
// Nếu arr[mid] = x, trả về chỉ số và kết thúc. if (arr[mid] == x)
if (arr[mid] == x) return mid;
return mid; // Nếu arr[mid] > x, cập nhật lại right
// Nếu arr[mid] > x, thực hiện tìm kiếm nửa trái của mảng if (arr[mid] > x)
if (arr[mid] > x) r = mid - 1;
return binarySearch(arr, l, mid - 1, x); // Nếu arr[mid] < x, cập nhật lại left
// Nếu arr[mid] < x, thực hiện tìm kiếm nửa phải của mảng if (arr[mid] < x)
return binarySearch(arr, mid + 1, r, x); l = mid + 1;
} }
// Nếu không tìm thấy return -1;
return -1; }
}
Chia để trị
❖ Một số bài toán khác
▪ Fast power: an = a*an-1 ; Nếu n chẵn: an = an/2 * an/2
▪ Bài toán tháp Hà Nội
▪ Các giải thuật sắp xếp: QuickSort, MergeSort
▪ Closet pair of points

❖Lưu ý
▪ Khi bài toán lớn được chia thành các bài toán nhỏ hơn mà những bài toán nhỏ hơn
này không đơn giản nhiều so với bài toán gốc thì không nên dùng kỹ thuật chia để
trị.
Bài toán tháp Hà Nội
▪ Mô tả bài toán: chuyển n đĩa từ cột A sang cột C có cột B làm trung gian, với yêu
cầu sau:
o Mỗi lần di chuyển 1 đĩa.
o Khi chuyển có thể dùng cột trung gian B.
o Trong quá trình chuyển các chồng đĩa ở các cột luôn được xếp đúng (đĩa có kích
thước bé đặt trên đĩa có kích thước lớn).
Bài toán tháp Hà Nội
Số đĩa là n có thể được giải với số bước tối thiểu là 2n-1

n=2 n=3
Bài toán tháp Hà Nội
▪ Tìm phần cơ sở và cách giải
n=1: HaNoiTower(1, A, B, C) : tìm dãy thao tác để chuyển chồng 1 đĩa từ cột A sang
cột C, lấy cột B làm cột trung gian.
Bài toán tháp Hà Nội
❖ Phân rã bài toán:
▪ HaNoiTower(n, A, B, C): chuyển n đĩa từ cột A sang cột C, lấy cột B làm trung gian
thành dãy tuần tự 3 công việc sau:
Chuyển (n-1) đĩa từ cột A sang cột B, lấy cột C làm trung gian :

Chuyển 1 đĩa từ cột A sang cột C :

Chuyển (n-1) đĩa từ cột B sang cột C, lấy A làm trung gian :
Bài toán tháp Hà Nội
❖ Cài đặt
Các vấn đề đệ quy thông dụng
❖ Lần ngược (Backtracking)
▪ Tại bước có nhiều lựa chọn, ta chọn
thử 1 bước để đi tiếp.
▪ Nếu không thành công thì “lần
ngược” chọn bước khác.
▪ Nếu đã thành công thì ghi nhận lời
giải này đồng thời “lần ngược” để
truy tìm lời giải mới.
▪ Thích hợp giải các bài toán kinh điển
như bài toán 8 hậu và bài toán mã đi
tuần.
Lưu ý
▪ Chỉ nên dùng phương pháp đệ quy để giải các bài toán kinh điển như
giải các vấn đề “chia để trị”, “lần ngược”.
▪ Vấn đề đệ quy không nhất thiết phải giải bằng phương pháp đệ quy, có
thể sử dụng phương pháp khác thay thế (khử đệ quy)
▪ Tiện cho người lập trình nhưng không tối ưu khi chạy trên máy.
▪ Bước đầu nên giải bằng đệ quy nhưng từng bước khử đệ quy để nâng
cao hiệu quả.
Edit Distance (option)
▪ Edit distance (hay còn gọi là Levenshtein distance) giữa hai chuỗi S1 và S2 là số
bước ít nhất biến chuỗi S1 thành chuỗi S2 thông qua 3 phép biến đổi là:
o xoá 1 ký tự (delete)
o thêm 1 ký tự ( insert)
o thay ký tự này bằng ký tự khác (replace)

▪ Ví dụ: Khoảng cách Levenshtein giữa 2 chuỗi "kitten" và "sitting" là 3, vì phải


dùng ít nhất 3 lần biến đổi.
kitten -> sitten (thay "k" bằng "s")
sitten -> sittin (thay "e" bằng "i")
sittin -> sitting (thêm ký tự "g")
Edit Distance
Ví dụ:
Input: str1 = "geek", str2 = "gesek"
Output: 1
We can convert str1 into str2 by inserting a 's'.

Input: str1 = "cat", str2 = "cut"


Output: 1
We can convert str1 into str2 by replacing 'a' with 'u'.

Input: str1 = "sunday", str2 = "saturday"


Output: 3
Replace 'n' with 'r’
Insert t
Insert a
Edit Distance
❖ Ứng dụng:
▪ Xử lý ngôn ngữ tự nhiên (Natural Language Processing- NLP): spell correction
▪ Bioinformatics: tính độ tương đồng của các chuỗi DNA (strings of the letters A, C, G and T)
▪ Optical Character Recognition (OCR): xem như một metric để đánh giá performance của hệ thống
OCR.

▪ Fuzzy search: tìm kiếm một xâu "gần giống" (thay vì "giống hệt") so với một xâu cho trước
▪ …
Edit Distance
▪ Solution: dựa vào
o Kỹ thuật Đệ quy
o Kỹ thuật Qui hoạch động (thường dùng)

*Tìm hiểu về kỹ thuật Qui hoạch động giải bài toán này
https://vi.wikipedia.org/wiki/Kho%E1%BA%A3ng_c%C3%A1ch_Levenshtein
http://www.giaithuatlaptrinh.com/?p=99
https://viblo.asia/p/khoang-cach-levenshtein-va-fuzzy-query-trong-elasticsearch-
jvElaOXAKkw
Edit Distance
❖ Dùng đệ quy:
▪ Idea: xử lý tất cả các ký tự trong cả hai chuỗi một cách tuần tự từ phải sang trái
Giả sử
m: Length of str1 (first string)
n: Length of str2 (second string)
▪ Điều kiện 1: Nếu chuỗi str1 là empty (m ==0), thêm (insert) tất cả các ký tự trong
chuỗi str2 vào chuỗi str1 (có ít nhất n phép biến đỏi)
▪ Điều kiện 2: Nếu chuỗi str2 là empty (n==0), xóa (delete) tất cả các ký tự trong
chuỗi str1 (có ít nhất m phép biến đỏi)
▪ Trường hợp m và n khác 0: Ta xét từng ký tự trong cả hai chuỗi từ phải sang trái.
Có hai trường hợp xảy ra
Edit distance
▪ TH1: Nếu hai ký tự cuối cùng của hai chuỗi giống nhau. Loại bỏ những
ký tự cuối và xem xét lại phần còn lại của hai chuỗi. Chúng ta lập lại
quá trình xử ký ( gọi đệ quy) cho hai chuỗi có độ dài m-1 , n-1 .

Ví dụ : xét hai chuỗi : “go” và “hallo” → gọi đệ quy tính edit distance
cho hai chuỗi “g” và “hall”
Edit distance
▪ TH2: Nếu hai ký tự cuối khác nhau (tồn tại một phép biến đổi, +1). Chúng ta xem
xét tất cả phép biến đôi trên ký tự cuối của chuỗi str1. Tính chi phí nhỏ nhất dựa
trên đệ quy cho ba phép biến đổi và lấy giá trị nhỏ nhất của ba giá trị

Insert: Recur for m and n-1


Delete: Recur for m-1 and n
Replace: Recur for m-1 and n-1
Edit distance
Ví dụ: xét hai chuỗi “g” và “hall” : hai ký tự cuối khác nhau. Xem xét ba trường hợp
xảy ra. Tìm số lượng phép biến đối ít nhất biên g thành hall.
▪ Nếu dùng Insert (Recur for m and n-1): nghĩa là thêm “l” vào chuỗi “g” ta được “gl” so
với chuỗi “hall”. Tiếp tục gọi đệ quy tính edit distance cho hai chuỗi “g” và “hal”
(chiều dài chuỗi thứ 2 giảm đi 1).
▪Nếu dùng Delete(Recur for m-1 and n): nghĩa là delete ký tư “g” ra chuỗi thứ 1 và trở
thành chuỗi empty. Tiếp tục gọi đệ quy tính edit distance cho hai chuỗi empty và
“hall” (chiều dài chuỗi thứ 1 giảm đi 1). Chuỗi thứ 1 trở thành “hallg”, sau đó delete
“g” để trở thành chuỗi thứ 2.
▪Nếu dùng Repale (Recur for m-1 and n-1): thay “g” trong chuỗi thứ 1 thành “l”. Tiếp
tục gọi đệ quy tính edit distance cho hai chuỗi empty và “hal” (chiều dài hai chuỗi
giảm di 1). Chuỗi thứ 1 trở thành “halg”, sau đó replace“g” thành “l” để trở thành
chuỗi thứ 2.
Closet Pair of Points (option)
Bài toán: tìm cặp điểm có khoảng cách (Euclid distance) gần nhất trong mặt phẳng.

Solution: Dùng đệ quy và chia để trị


Closet Pair of Points
Input: Mảng P[] chứa n điểm trong mặt phẳng Oxy
Output: Khoảng cách nhỏ nhất giữa hai điểm trong mảng
P[]
** Tiền xử lý: sắp xếp các điểm tăng dần theo tọa độ x
Thuật toán : 7 bước
B1: Tìm điẻm giữa (mid) trong mảng P[], có thể láy P[n/2]
là điểm giữa.
B2: (Divide) Chia mảng P thành hai phần: PL và PR. PL:
0 đến n/2. PR: n/2+1 đến n-1
B3: (Conquer) Tính khoảng cách nhỏ nhất trong hai mảng
con dùng đệ quy. Giả sử gọi các khoảng cách đó là dl và
dr .
(combine) Tìm khoảng cách nhỏ nhất d = min(dl, dr)
Closet Pair of Points
B4: Xem xét các cặp điểm: một điẻm
nằm bên trái đường biên, điểm còn lại
nằm bên phải.
▪ Tìm các điẻm có khoảng cách (theo
tọa độ x) đến đường biên nhỏ hơn d .
Lưu các điểm đó vào mảng strip[].
B5: Sắp xếp các điểm trong mảng
strip[] theo tọa độ y.
B6: Tính khoảng cách nhỏ nhất ds giữa
các điểm trong strip[] thỏa điều kiện
yi-yj < d.
B7: Sau cùng, tìm giá trị nhỏ nhất giữa
d và ds , return min(d,ds)
Bài tập
1. Viết hàm chuyển cơ số từ hệ thập phân sang hệ nhị phân
a) Dùng đệ quy
b) Không dùng đệ quy

2. Viết hàm tính tổ hợp

a) Dùng đệ quy (dựa vào công thức Pascal)


b) Không dùng đệ quy
Bài tập
3. Viết hàm đệ quy tìm chiều dài của một chuỗi.
4.
Bài tập
5.
Bài tập
6.

7. Cho một mảng A đã được sắp xếp tăng dần. Viết chương trình tìm kiếm một phần tử k
trong mảng A
a) Không dùng đệ quy (tìm kiếm tuyến tính)
b) Dùng đệ quy (tìm kiếm nhị phân)
8. Viết hàm tính fast power an dùng chia để trị
Bài tập (option)
1. Tìm hiều về bài toán 8 quân hậu

2. Tìm hiểu về bài toán mã đi tuần


Bài tập (option)
1. Cài đặt bài toán Edit Distance
a) Nhập hai chuỗi từ bàn phím. Xuất kết quả ra màn hình.
b) Thao tác trên FILE
Input: file text chứa các cặp chuỗi cần tính. Mỗi cặp chuỗi cách nhau bằng một khoảng trắng.
Output: lưu kết quả ra file

Input.txt Output.txt
Hello Hell 1
go hallo 4
kitten sitting 3

2. Cài đặt bài toán Closet Pair of Points

You might also like