Tải bản đầy đủ (.docx) (10 trang)

Nội dung CTDLGT phỏng vấn Android dev ở Fsoft chắc chắn pass

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (364.08 KB, 10 trang )

CẤU TRÚC DỮ LIỆU
1. Cấu trúc dữ liệu là gì?
Cấu trúc dữ liệu là cách lưu trữ, tổ chức dữ liệu một cách logic để dữ liệu có thể được sử dụng một
cách hiệu quả.
Cấu trúc dữ liệu thường đi với thuật toán. Mỗi thuật toán phù hợp với một loại cấu trúc dữ liệu cụ
thể. Việc chọn ctdl phù hợp giúp tăng hiệu năng chương trình.
Cấu trúc dữ liệu + giải thuật = chương trình.
2. Stack (ngăn xếp)
Ngăn xếp (stack) hoạt động theo nguyên tắc “vào sau ra trước - LIFO”.
Ngăn xếp là một container chứa các phần tử. Có hai thao tác cơ bản với ngăn xếp là push và pop. Push
thêm một phần tử vào cuối ngăn xếp. Pop trả về phần tử cuối ngăn xếp và loại bỏ nó khỏi ngăn xếp.
Ta tưởng tượng ngăn xếp như một chồng sách. Push là đặt quyển sách lên trên chồng sách (chỉ có thể
đặt lên trên cùng), pop là lấy quyển sách khỏi chồng sách (chỉ có thể lấy quyển sách trên cùng).
3. Hàng đợi (queue)
Hàng đợi là một cấu trúc dữ liệu để chứa các đối tượng làm việc theo cơ chế “vào trước ra trước FIFO”. Một đối tượng luôn được thêm vào cuối hàng đợi và lấy ra ở đầu hàng đợi.
Ta tưởng tượng hàng đợi (queue) như việc xếp hàng mua vé xem phim. Người đến sau phải đứng cuối
hàng, người đến trước sẽ được mua vé trước.
4. Mảng (array)
- Mảng gồm một tập các phần tử, các phần tử được truy xuất sử dụng index.
- Mảng có kích thước cố định.
- Khơng thể thực hiện thêm hoặc xóa phần tử do kích thước cố định.
- Về bản chất array là một vùng nhớ gồm nhiều phần tử nằm liền kề nhau.
- Đặc điểm: truy xuất phần tử nhanh nhờ index (độ phức tạp O(1)).
5. Linked list
- Đối với array việc thêm phần tử là khơng thể hoặc ta có thể thêm phần tử mới bằng việc tạo một
mảng có kích thước lớn hơn, copy mảng cũ vào mảng mới và thêm phần tử mới vào ngay sau mảng
cũ. Nhưng việc này tốn khá nhiều thời gian. Do vậy người ta sáng tạo ra Linked List.


- Mỗi phần tử trong Linked List sẽ có một con trỏ trỏ tới phần tử phía sau nó. Khi muốn thêm phần tử
ta chỉ việc tạo phần tử mới và cho phần tử đó trỏ tới phần tử đầu danh sách. Việc xóa phần tử cũng


tương tự, ta chỉ việc cho Linked List trỏ tới phần tử thứ 2. Cả thêm và xóa phần tử đều có độ phức tạp
O(1).
- Linked List nên được dùng khi cần lưu trữ một danh sách có số phần tử khơng cố định (khơng biết
trước số lượng phần tử).
- Linked List có 2 loại là: Single-Linked List và Double-linked List. Phần tử trong Single chỉ chứa con trỏ
trỏ đến phần tử tiếp theo. Phần tử trong Double chứa 2 con trỏ, trỏ về phía trước và phía sau.
6. Bảng băm (hash table)
- Bảng băm dùng để lưu các phần tử có dạng (key, value).
- Key sẽ được đưa vào hàm băm (hash function) để tạo giá trị băm (có thể gọi là index)
- Dựa vào giá trị băm này (index), phần tử được đưa vào bucket.

Trong hình trên key là tên người, index là các số 00, 01, 02,…, giá trị là số điện thoại 521-8976,… Key
“John Smith” sau khi được băm tạo ra giá trị băm 02, “Lisa Smith” tạo ra giá trị băm 01.
- Khi truy xuất phần tử, ta sử dụng key. Từ key ta suy ra index, từ index ta lấy được giá trị.
- Tuy nhiên có những trường hợp, 2 key cùng có 1 giá trị băm (người ta gọi là hash collision). Khi đó 1
bucket sẽ chứa > 1 phần tử và ta phải duyệt qua tất cả các phần tử trong bucket để tìm ra phần tử
ứng với key. Hình dưới thể hiện khi một bucket chứa nhiều phần tử (1 bucket sẽ là 1 Linked List chứa
các phần tử).


Hai key “John Smith” và “Sandra Dee” đều tạo ra giá trị băm (index) là 152.
- Gọi n là số phần tử trong Hashtable và k là số bucket. Giá trị n/k <= 1 thì độ phức tạp của các thao
tác thêm, tìm kiếm, xóa phần tử trong Hashtable là O(1). Trường hợp xấu nhất là O(n) khi tất cả các
phần tử cùng nằm trong 1 bucket.
7. Graph
Đồ thị (graph) là tập hợp nhiều điểm, các điểm này được nối với nhau bằng các cạnh. Đỉnh không
được nối tới bất kỳ đỉnh nào ta gọi nó là đỉnh cơ lập.
Có 2 loại đồ thị là đồ thi vô hướng và đồ thị có hướng.
Ứng dụng của đồ thị: tìm đường đi ngắn nhất giữa 2 vị trí (ứng dụng bản đồ, truyền gói tin trên mạng
máy tính), tìm bạn bè chung, người quen trên mạng xã hội, trí tuệ nhân tạo,…

Các giải thuật dùng cho đồ thị: BFS – tìm kiếm theo chiều rộng, DFS – tìm kiếm theo chiều sâu,
Bellman-Ford, Dijkstra, Ford-Fulkerson,…
8. Cây (tree)
- Cây cũng là một dạng đồ thị.
- Một cây sẽ có một node gốc (root).
- Mỗi node sẽ có 1 hoặc nhiều node con.
- Những node khơng có node con gọi là node lá.
- Một cây sẽ bao gồm nhiều cây con (subtree). Mỗi cây con sẽ bao gồm 1 node gốc vào các node con
của nó.


- Tree có 2 biến thể phổ biến và được dùng nhiều nhất là:
+ Binary tree: Mỗi node sẽ có tối đa 2 node con. Lần lượt gọi tên là node trái và node phải.
+ Binary Search tree: Biến thể của Binary Tree. Mỗi node có tối đa 2 node con. Giá trị của node con
bên trái phải nhỏ hơn node cha của nó. Giá trị của node con bên phải phải lớn hơn node cha của nó.

Hình trên là ví dụ của binary search tree.

Đánh giá các data structure


Nguồn: />
THUẬT TỐN
1. Thuật tốn sinh (Generation)
Phương pháp sinh có thể áp dụng để giải bài toán liệt kê tổ hợp đặt ra nếu như 2 điều kiện sau thõa
mãn:
- Có thể xác định được một thứ tự trên tập các cấu hình (phần tử cần in ra) cần liệt kê. Biết được cấu
hình đầu tiên và cấu hình cuối cùng.
- Từ một cấu hình chưa phải cuối cùng, ta xây dựng được thuật tốn sinh ra cấu hình đứng ngay sau
nó theo thứ tự.



2. Đệ quy (Recursion)
Thuật tốn giải bài tốn P thơng qua bài toán P’ giống như P gọi là giải thuật đệ quy. Một hàm được
gọi là đệ quy nếu nó gọi đến chính nó.

Đệ quy giống như búp bê Nga. Bên trong một con búp bê lại chứa một con khác giống hệt.
Hoặc tưởng tượng đệ quy giống như khi ta xem ta livestream. Ta thấy ta trong màn hình, trong màn
hình lại có 1 màn hình khác giống hệt, cứ như vậy.
Một bài toán giải được bằng đệ quy nếu nó thõa mãn 2 điều kiện:
- Phân tích được: Có thể giải bài tốn P bằng bài tốn P’ giống như P và chỉ khác P ở dữ liệu đầu vào.
Việc giải bài toán P’ cũng được phân tích giống như P.
- Điều kiện dừng (thuật tốn khơng thể là vô tận – phải đến một lúc nào đó dừng lại): Dãy các bài tốn
P’ giống P phải là hữu hạn và sẽ dừng lại ở một bài tốn nào đó (bài tốn này có thể giải trực tiếp
khơng cần gọi đến bài tốn con).

3. Quay lui (Backtrack)
Thuật toán quay lui dùng để giải bài toán liệt kê các cấu hình. Mỗi cấu hình được xây dựng bằng cách
xây dựng từng phần tử của cấu hình đó. Mỗi phần tử được chọn bằng cách thử tất cả các khả năng có
thể.


Giả sử ta cần xác định cấu hình X = (x1, x2,…, Xn). Ứng với mỗi phần tử xi ta có ni khả năng cần lựa
chọn. Ứng với mỗi khả năng j thuộc ni dành cho phần tử xi ta cần thực hiện:
- Kiểm tra xem khả năng j có được chấp thuận cho phần tử xi hay không? Nếu j được chấp thuận thì
nếu xi là phần tử cuối cùng (tức i = n) thì ta ghi nhận nghiệm của bài toán. Nếu xi chưa phải phần tử
cuối cùng, ta tiếp tục xác định phần tử thứ i+1.
- Nếu khơng có khả năng j nào được chấp thuận cho phần tử xi, thì ta quay lại bước trước đó (i-1) để
thử các khả năng khác.
Thuật toán quay lui:


4. Quy hoạch động
Thuật tốn quy hoạch động có đặc điểm sau:
- Bài toán lớn được phân ra thành bài toán con. Việc phối hợp kết quả của các bài toán con cho ta kết
quả của bài tốn lớn.
- Cần có kết quả cơ sở. Từ kết quả cơ sở sinh ra các kết quả của bài tốn lớn hơn.
- Cần cơng thức truy hồi: là công thức phối hợp kết quả của các bài toán con để tạo ra kết quả của bài
toán lớn.
- Tại mỗi bước, cần lữu trữ lại kết quả của các bài tốn con cho mục đích sử dụng lại (đây là điểm khác
biệt so với thuật tốn đệ quy, nhờ đó giảm chi phí tính tốn -> nhanh hơn đệ quy). Do đó cần có đủ
bộ nhớ.
Ví dụ dùng quy hoạch động để giải bài tốn: Tìm số Fibonacci thứ n.
Bước 1: Tìm kết quả cơ sở
F[1] = 1, F[2] = 1.
Bước 2: Tìm cơng thức truy hồi


F[i] = F[i-1] + F[i-2].
Bước 3: Tính F[n] sử dụng công thức truy hồi.
Giải thuật:

5. Chia để trị
6. Tham lam (Greedy algorithm)
- Thuật tốn tham lam là thuật tốn ln chọn lựa chọn tối ưu cục bộ với mong muốn tìm ra lựa chọn
tối ưu tồn cục. Tại mỗi bước, thuật tốn ln chọn lựa chọn tốt nhất.
- Nhưng do khơng có cái nhìn tổng qt nên thuật tốn có thể khơng cho phương án tối ưu.
Thuật tốn Greedy bao gồm 5 thành phần chính:
1. Một tập các ứng viên mà giải pháp thực hiện tạo ra.
2. Một hàm lựa chọn (selection fuction) để chọn ứng viên tốt nhất cho giải pháp.
3. Một hàm thực thi (feasibility function) được sử dụng để xác định các ứng viên có thể có

đóng góp cho giải pháp thực thi.
4. Một hàm mục tiêu (objective function) dùng để xác định giá trị của phương pháp hoặc một
phần của giải pháp.
5. Một hàm giải pháp (solution function) dùng để xác định khi nào giải pháp kết thúc.

CÁC THUẬT TOÁN SẮP XẾP

a/p/cac-thuat-toan-sap-xep-co-ban-Eb85ooNO52G


1. Thuật toán Quick sort
- Chọn 1 phần tử là phần tử chốt gọi là pivot
- Chia mảng thành 2 phần: phần bên trái gồm các phần tử nhỏ hơn hoặc bằng pivot, phần bên phải
gồm các phần tử lớn hơn pivot
- Thực hiện quick sort trên 2 phần trái và phải đó.
- Cuối cùng ta được mảng đã sắp xếp là: LpR (L là phần bên trái, p là phần tử chốt pivot, R là phần bên
phải)
2. Thuật toán Merge sort
- Là kiểu thuật toán chia để trị
- Đầu tiên chia đôi mảng thành 2 dãy con: dãy con bên trái và dãy con bên phải
- Thực hiện thuật toán mergeSort() trên 2 dãy con này (tức là sắp xếp 2 dãy con này).
- Trộn (merge) 2 dãy con được sắp xếp để thu được dãy được sắp xếp.
3. Thuật toán Heap Sort
- Đầu tiên đưa mảng A cần sắp xếp về dạng heap (đống): phần tử thứ i sẽ là cha của 2 phần tử thứ 2*i
+ 1 và 2*i + 2.
- Thực hiện hốn đổi vị trí của các node trong heap (bản chất là một cây nhị phân) sao cho node cha
luôn lớn hơn node con -> node gốc sẽ có giá trị lớn nhất.
- Thực hiện đưa node gốc về cuối dãy.
- Thực hiện vun đống với các node con còn lại. Sau mỗi lần vun đống ta đưa node gốc về cuối dãy.
Thực hiện vun đống đến khi chỉ còn 1 node cuối cùng -> Khi đó dãy đã được sắp xếp theo thứ tự từ bé

đến lớn.

CÁC THUẬT TỐN TÌM KIẾM
/>1. Tìm kiếm tuyến tính
- Mảng khơng cần được sắp xếp trước
- Kiểm tra tuần tự từng phần tử của mảng đến khi nào tìm thấy hoặc duyệt hết các phần tử của mảng
nhưng khơng tìm thấy.
2. Tìm kiếm nhị phân


- Mảng đã được sắp xếp tăng dần
- Đầu tiên so sánh phần tử cần tìm x với phần tử nằm ở giữa mảng
- Nếu x nhỏ hơn thì nó chỉ có thể nằm ở nửa bên trái. Nếu x lớn hơn thì nó chỉ có thể nằm ở nửa bên
phải.
- Khi xác định được x nằm ở nửa nào thì ta lặp lại thuật tốn với nửa đó. Như vậy số lần kiểm tra giảm
đi nhiều do ko phải mất cơng kiểm tra những phần tử thuộc nửa cịn lại.
3. Tìm kiếm nội suy
- Là cải tiến của thuật tốn tìm kiếm nhị phân
- Thay vì chia đơi mảng (so sánh phần tử cần tìm với phần tử nằm chính giữa mảng), thuật tốn này
tính phần tử giữa theo cơng thức sau:

, trong đó x là phần tử cần tìm
- Sử dụng cơng thức này giúp thu gọn khoảng tìm kiếm hơn.



×